LCOV - code coverage report
Current view: top level - gcc - vec.h (source / functions) Hit Total Coverage
Test: gcc.info Lines: 346 364 95.1 %
Date: 2023-07-19 08:18:47 Functions: 354 397 89.2 %

          Line data    Source code
       1             : /* Vector API for GNU compiler.
       2             :    Copyright (C) 2004-2023 Free Software Foundation, Inc.
       3             :    Contributed by Nathan Sidwell <nathan@codesourcery.com>
       4             :    Re-implemented in C++ by Diego Novillo <dnovillo@google.com>
       5             : 
       6             : This file is part of GCC.
       7             : 
       8             : GCC is free software; you can redistribute it and/or modify it under
       9             : the terms of the GNU General Public License as published by the Free
      10             : Software Foundation; either version 3, or (at your option) any later
      11             : version.
      12             : 
      13             : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      14             : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      15             : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      16             : for more details.
      17             : 
      18             : You should have received a copy of the GNU General Public License
      19             : along with GCC; see the file COPYING3.  If not see
      20             : <http://www.gnu.org/licenses/>.  */
      21             : 
      22             : #ifndef GCC_VEC_H
      23             : #define GCC_VEC_H
      24             : 
      25             : /* Some gen* file have no ggc support as the header file gtype-desc.h is
      26             :    missing.  Provide these definitions in case ggc.h has not been included.
      27             :    This is not a problem because any code that runs before gengtype is built
      28             :    will never need to use GC vectors.*/
      29             : 
      30             : extern void ggc_free (void *);
      31             : extern size_t ggc_round_alloc_size (size_t requested_size);
      32             : extern void *ggc_realloc (void *, size_t MEM_STAT_DECL);
      33             : 
      34             : /* Templated vector type and associated interfaces.
      35             : 
      36             :    The interface functions are typesafe and use inline functions,
      37             :    sometimes backed by out-of-line generic functions.  The vectors are
      38             :    designed to interoperate with the GTY machinery.
      39             : 
      40             :    There are both 'index' and 'iterate' accessors.  The index accessor
      41             :    is implemented by operator[].  The iterator returns a boolean
      42             :    iteration condition and updates the iteration variable passed by
      43             :    reference.  Because the iterator will be inlined, the address-of
      44             :    can be optimized away.
      45             : 
      46             :    Each operation that increases the number of active elements is
      47             :    available in 'quick' and 'safe' variants.  The former presumes that
      48             :    there is sufficient allocated space for the operation to succeed
      49             :    (it dies if there is not).  The latter will reallocate the
      50             :    vector, if needed.  Reallocation causes an exponential increase in
      51             :    vector size.  If you know you will be adding N elements, it would
      52             :    be more efficient to use the reserve operation before adding the
      53             :    elements with the 'quick' operation.  This will ensure there are at
      54             :    least as many elements as you ask for, it will exponentially
      55             :    increase if there are too few spare slots.  If you want reserve a
      56             :    specific number of slots, but do not want the exponential increase
      57             :    (for instance, you know this is the last allocation), use the
      58             :    reserve_exact operation.  You can also create a vector of a
      59             :    specific size from the get go.
      60             : 
      61             :    You should prefer the push and pop operations, as they append and
      62             :    remove from the end of the vector. If you need to remove several
      63             :    items in one go, use the truncate operation.  The insert and remove
      64             :    operations allow you to change elements in the middle of the
      65             :    vector.  There are two remove operations, one which preserves the
      66             :    element ordering 'ordered_remove', and one which does not
      67             :    'unordered_remove'.  The latter function copies the end element
      68             :    into the removed slot, rather than invoke a memmove operation.  The
      69             :    'lower_bound' function will determine where to place an item in the
      70             :    array using insert that will maintain sorted order.
      71             : 
      72             :    Vectors are template types with three arguments: the type of the
      73             :    elements in the vector, the allocation strategy, and the physical
      74             :    layout to use
      75             : 
      76             :    Four allocation strategies are supported:
      77             : 
      78             :         - Heap: allocation is done using malloc/free.  This is the
      79             :           default allocation strategy.
      80             : 
      81             :         - GC: allocation is done using ggc_alloc/ggc_free.
      82             : 
      83             :         - GC atomic: same as GC with the exception that the elements
      84             :           themselves are assumed to be of an atomic type that does
      85             :           not need to be garbage collected.  This means that marking
      86             :           routines do not need to traverse the array marking the
      87             :           individual elements.  This increases the performance of
      88             :           GC activities.
      89             : 
      90             :    Two physical layouts are supported:
      91             : 
      92             :         - Embedded: The vector is structured using the trailing array
      93             :           idiom.  The last member of the structure is an array of size
      94             :           1.  When the vector is initially allocated, a single memory
      95             :           block is created to hold the vector's control data and the
      96             :           array of elements.  These vectors cannot grow without
      97             :           reallocation (see discussion on embeddable vectors below).
      98             : 
      99             :         - Space efficient: The vector is structured as a pointer to an
     100             :           embedded vector.  This is the default layout.  It means that
     101             :           vectors occupy a single word of storage before initial
     102             :           allocation.  Vectors are allowed to grow (the internal
     103             :           pointer is reallocated but the main vector instance does not
     104             :           need to relocate).
     105             : 
     106             :    The type, allocation and layout are specified when the vector is
     107             :    declared.
     108             : 
     109             :    If you need to directly manipulate a vector, then the 'address'
     110             :    accessor will return the address of the start of the vector.  Also
     111             :    the 'space' predicate will tell you whether there is spare capacity
     112             :    in the vector.  You will not normally need to use these two functions.
     113             : 
     114             :    Notes on the different layout strategies
     115             : 
     116             :    * Embeddable vectors (vec<T, A, vl_embed>)
     117             :    
     118             :      These vectors are suitable to be embedded in other data
     119             :      structures so that they can be pre-allocated in a contiguous
     120             :      memory block.
     121             : 
     122             :      Embeddable vectors are implemented using the trailing array
     123             :      idiom, thus they are not resizeable without changing the address
     124             :      of the vector object itself.  This means you cannot have
     125             :      variables or fields of embeddable vector type -- always use a
     126             :      pointer to a vector.  The one exception is the final field of a
     127             :      structure, which could be a vector type.
     128             : 
     129             :      You will have to use the embedded_size & embedded_init calls to
     130             :      create such objects, and they will not be resizeable (so the
     131             :      'safe' allocation variants are not available).
     132             : 
     133             :      Properties of embeddable vectors:
     134             : 
     135             :           - The whole vector and control data are allocated in a single
     136             :             contiguous block.  It uses the trailing-vector idiom, so
     137             :             allocation must reserve enough space for all the elements
     138             :             in the vector plus its control data.
     139             :           - The vector cannot be re-allocated.
     140             :           - The vector cannot grow nor shrink.
     141             :           - No indirections needed for access/manipulation.
     142             :           - It requires 2 words of storage (prior to vector allocation).
     143             : 
     144             : 
     145             :    * Space efficient vector (vec<T, A, vl_ptr>)
     146             : 
     147             :      These vectors can grow dynamically and are allocated together
     148             :      with their control data.  They are suited to be included in data
     149             :      structures.  Prior to initial allocation, they only take a single
     150             :      word of storage.
     151             : 
     152             :      These vectors are implemented as a pointer to embeddable vectors.
     153             :      The semantics allow for this pointer to be NULL to represent
     154             :      empty vectors.  This way, empty vectors occupy minimal space in
     155             :      the structure containing them.
     156             : 
     157             :      Properties:
     158             : 
     159             :         - The whole vector and control data are allocated in a single
     160             :           contiguous block.
     161             :         - The whole vector may be re-allocated.
     162             :         - Vector data may grow and shrink.
     163             :         - Access and manipulation requires a pointer test and
     164             :           indirection.
     165             :         - It requires 1 word of storage (prior to vector allocation).
     166             : 
     167             :    An example of their use would be,
     168             : 
     169             :    struct my_struct {
     170             :      // A space-efficient vector of tree pointers in GC memory.
     171             :      vec<tree, va_gc, vl_ptr> v;
     172             :    };
     173             : 
     174             :    struct my_struct *s;
     175             : 
     176             :    if (s->v.length ()) { we have some contents }
     177             :    s->v.safe_push (decl); // append some decl onto the end
     178             :    for (ix = 0; s->v.iterate (ix, &elt); ix++)
     179             :      { do something with elt }
     180             : */
     181             : 
     182             : /* Support function for statistics.  */
     183             : extern void dump_vec_loc_statistics (void);
     184             : 
     185             : /* Hashtable mapping vec addresses to descriptors.  */
     186             : extern htab_t vec_mem_usage_hash;
     187             : 
     188             : /* Control data for vectors.  This contains the number of allocated
     189             :    and used slots inside a vector.  */
     190             : 
     191             : struct vec_prefix
     192             : {
     193             :   /* FIXME - These fields should be private, but we need to cater to
     194             :              compilers that have stricter notions of PODness for types.  */
     195             : 
     196             :   /* Memory allocation support routines in vec.cc.  */
     197             :   void register_overhead (void *, size_t, size_t CXX_MEM_STAT_INFO);
     198             :   void release_overhead (void *, size_t, size_t, bool CXX_MEM_STAT_INFO);
     199             :   static unsigned calculate_allocation (vec_prefix *, unsigned, bool);
     200             :   static unsigned calculate_allocation_1 (unsigned, unsigned);
     201             : 
     202             :   /* Note that vec_prefix should be a base class for vec, but we use
     203             :      offsetof() on vector fields of tree structures (e.g.,
     204             :      tree_binfo::base_binfos), and offsetof only supports base types.
     205             : 
     206             :      To compensate, we make vec_prefix a field inside vec and make
     207             :      vec a friend class of vec_prefix so it can access its fields.  */
     208             :   template <typename, typename, typename> friend struct vec;
     209             : 
     210             :   /* The allocator types also need access to our internals.  */
     211             :   friend struct va_gc;
     212             :   friend struct va_gc_atomic;
     213             :   friend struct va_heap;
     214             : 
     215             :   unsigned m_alloc : 31;
     216             :   unsigned m_using_auto_storage : 1;
     217             :   unsigned m_num;
     218             : };
     219             : 
     220             : /* Calculate the number of slots to reserve a vector, making sure that
     221             :    RESERVE slots are free.  If EXACT grow exactly, otherwise grow
     222             :    exponentially.  PFX is the control data for the vector.  */
     223             : 
     224             : inline unsigned
     225   564531828 : vec_prefix::calculate_allocation (vec_prefix *pfx, unsigned reserve,
     226             :                                   bool exact)
     227             : {
     228   564531828 :   if (exact)
     229    74447034 :     return (pfx ? pfx->m_num : 0) + reserve;
     230   490084794 :   else if (!pfx)
     231   421742962 :     return MAX (4, reserve);
     232    68341832 :   return calculate_allocation_1 (pfx->m_alloc, pfx->m_num + reserve);
     233             : }
     234             : 
     235             : template<typename, typename, typename> struct vec;
     236             : 
     237             : /* Valid vector layouts
     238             : 
     239             :    vl_embed     - Embeddable vector that uses the trailing array idiom.
     240             :    vl_ptr       - Space efficient vector that uses a pointer to an
     241             :                   embeddable vector.  */
     242             : struct vl_embed { };
     243             : struct vl_ptr { };
     244             : 
     245             : 
     246             : /* Types of supported allocations
     247             : 
     248             :    va_heap      - Allocation uses malloc/free.
     249             :    va_gc        - Allocation uses ggc_alloc.
     250             :    va_gc_atomic - Same as GC, but individual elements of the array
     251             :                   do not need to be marked during collection.  */
     252             : 
     253             : /* Allocator type for heap vectors.  */
     254             : struct va_heap
     255             : {
     256             :   /* Heap vectors are frequently regular instances, so use the vl_ptr
     257             :      layout for them.  */
     258             :   typedef vl_ptr default_layout;
     259             : 
     260             :   template<typename T>
     261             :   static void reserve (vec<T, va_heap, vl_embed> *&, unsigned, bool
     262             :                        CXX_MEM_STAT_INFO);
     263             : 
     264             :   template<typename T>
     265             :   static void release (vec<T, va_heap, vl_embed> *&);
     266             : };
     267             : 
     268             : 
     269             : /* Allocator for heap memory.  Ensure there are at least RESERVE free
     270             :    slots in V.  If EXACT is true, grow exactly, else grow
     271             :    exponentially.  As a special case, if the vector had not been
     272             :    allocated and RESERVE is 0, no vector will be created.  */
     273             : 
     274             : template<typename T>
     275             : inline void
     276    91197161 : va_heap::reserve (vec<T, va_heap, vl_embed> *&v, unsigned reserve, bool exact
     277             :                   MEM_STAT_DECL)
     278             : {
     279    91197161 :   size_t elt_size = sizeof (T);
     280             :   unsigned alloc
     281    91197161 :     = vec_prefix::calculate_allocation (v ? &v->m_vecpfx : 0, reserve, exact);
     282    91197161 :   gcc_checking_assert (alloc);
     283             : 
     284             :   if (GATHER_STATISTICS && v)
     285             :     v->m_vecpfx.release_overhead (v, elt_size * v->allocated (),
     286             :                                   v->allocated (), false);
     287             : 
     288    91197161 :   size_t size = vec<T, va_heap, vl_embed>::embedded_size (alloc);
     289   199756324 :   unsigned nelem = v ? v->length () : 0;
     290    91197161 :   v = static_cast <vec<T, va_heap, vl_embed> *> (xrealloc (v, size));
     291    91197161 :   v->embedded_init (alloc, nelem);
     292             : 
     293             :   if (GATHER_STATISTICS)
     294             :     v->m_vecpfx.register_overhead (v, alloc, elt_size PASS_MEM_STAT);
     295    91197161 : }
     296             : 
     297             : 
     298             : #if GCC_VERSION >= 4007
     299             : #pragma GCC diagnostic push
     300             : #pragma GCC diagnostic ignored "-Wfree-nonheap-object"
     301             : #endif
     302             : 
     303             : /* Free the heap space allocated for vector V.  */
     304             : 
     305             : template<typename T>
     306             : void
     307    69805239 : va_heap::release (vec<T, va_heap, vl_embed> *&v)
     308             : {
     309    69805239 :   size_t elt_size = sizeof (T);
     310      181327 :   if (v == NULL)
     311             :     return;
     312             : 
     313             :   if (GATHER_STATISTICS)
     314             :     v->m_vecpfx.release_overhead (v, elt_size * v->allocated (),
     315             :                                   v->allocated (), true);
     316    65202661 :   ::free (v);
     317    65200592 :   v = NULL;
     318             : }
     319             : 
     320             : #if GCC_VERSION >= 4007
     321             : #pragma GCC diagnostic pop
     322             : #endif
     323             : 
     324             : /* Allocator type for GC vectors.  Notice that we need the structure
     325             :    declaration even if GC is not enabled.  */
     326             : 
     327             : struct va_gc
     328             : {
     329             :   /* Use vl_embed as the default layout for GC vectors.  Due to GTY
     330             :      limitations, GC vectors must always be pointers, so it is more
     331             :      efficient to use a pointer to the vl_embed layout, rather than
     332             :      using a pointer to a pointer as would be the case with vl_ptr.  */
     333             :   typedef vl_embed default_layout;
     334             : 
     335             :   template<typename T, typename A>
     336             :   static void reserve (vec<T, A, vl_embed> *&, unsigned, bool
     337             :                        CXX_MEM_STAT_INFO);
     338             : 
     339             :   template<typename T, typename A>
     340             :   static void release (vec<T, A, vl_embed> *&v);
     341             : };
     342             : 
     343             : 
     344             : /* Free GC memory used by V and reset V to NULL.  */
     345             : 
     346             : template<typename T, typename A>
     347             : inline void
     348      353360 : va_gc::release (vec<T, A, vl_embed> *&v)
     349             : {
     350      261359 :   if (v)
     351      134279 :     ::ggc_free (v);
     352      350931 :   v = NULL;
     353             : }
     354             : 
     355             : 
     356             : /* Allocator for GC memory.  Ensure there are at least RESERVE free
     357             :    slots in V.  If EXACT is true, grow exactly, else grow
     358             :    exponentially.  As a special case, if the vector had not been
     359             :    allocated and RESERVE is 0, no vector will be created.  */
     360             : 
     361             : template<typename T, typename A>
     362             : void
     363   473334667 : va_gc::reserve (vec<T, A, vl_embed> *&v, unsigned reserve, bool exact
     364             :                 MEM_STAT_DECL)
     365             : {
     366             :   unsigned alloc
     367   473334667 :     = vec_prefix::calculate_allocation (v ? &v->m_vecpfx : 0, reserve, exact);
     368   473334667 :   if (!alloc)
     369             :     {
     370           0 :       ::ggc_free (v);
     371           0 :       v = NULL;
     372           0 :       return;
     373             :     }
     374             : 
     375             :   /* Calculate the amount of space we want.  */
     376   473334667 :   size_t size = vec<T, A, vl_embed>::embedded_size (alloc);
     377             : 
     378             :   /* Ask the allocator how much space it will really give us.  */
     379   946669334 :   size = ::ggc_round_alloc_size (size);
     380             : 
     381             :   /* Adjust the number of slots accordingly.  */
     382   473334667 :   size_t vec_offset = sizeof (vec_prefix);
     383   473334667 :   size_t elt_size = sizeof (T);
     384   473334667 :   alloc = (size - vec_offset) / elt_size;
     385             : 
     386             :   /* And finally, recalculate the amount of space we ask for.  */
     387   473334667 :   size = vec_offset + alloc * elt_size;
     388             : 
     389   473334667 :   unsigned nelem = v ? v->length () : 0;
     390   473334667 :   v = static_cast <vec<T, A, vl_embed> *> (::ggc_realloc (v, size
     391             :                                                                PASS_MEM_STAT));
     392   946669334 :   v->embedded_init (alloc, nelem);
     393             : }
     394             : 
     395             : 
     396             : /* Allocator type for GC vectors.  This is for vectors of types
     397             :    atomics w.r.t. collection, so allocation and deallocation is
     398             :    completely inherited from va_gc.  */
     399             : struct va_gc_atomic : va_gc
     400             : {
     401             : };
     402             : 
     403             : 
     404             : /* Generic vector template.  Default values for A and L indicate the
     405             :    most commonly used strategies.
     406             : 
     407             :    FIXME - Ideally, they would all be vl_ptr to encourage using regular
     408             :            instances for vectors, but the existing GTY machinery is limited
     409             :            in that it can only deal with GC objects that are pointers
     410             :            themselves.
     411             : 
     412             :            This means that vector operations that need to deal with
     413             :            potentially NULL pointers, must be provided as free
     414             :            functions (see the vec_safe_* functions above).  */
     415             : template<typename T,
     416             :          typename A = va_heap,
     417             :          typename L = typename A::default_layout>
     418             : struct GTY((user)) vec
     419             : {
     420             : };
     421             : 
     422             : /* Allow C++11 range-based 'for' to work directly on vec<T>*.  */
     423             : template<typename T, typename A, typename L>
     424    24797963 : T* begin (vec<T,A,L> *v) { return v ? v->begin () : nullptr; }
     425             : template<typename T, typename A, typename L>
     426    24741039 : T* end (vec<T,A,L> *v) { return v ? v->end () : nullptr; }
     427             : template<typename T, typename A, typename L>
     428             : const T* begin (const vec<T,A,L> *v) { return v ? v->begin () : nullptr; }
     429             : template<typename T, typename A, typename L>
     430             : const T* end (const vec<T,A,L> *v) { return v ? v->end () : nullptr; }
     431             : 
     432             : /* Generic vec<> debug helpers.
     433             : 
     434             :    These need to be instantiated for each vec<TYPE> used throughout
     435             :    the compiler like this:
     436             : 
     437             :     DEFINE_DEBUG_VEC (TYPE)
     438             : 
     439             :    The reason we have a debug_helper() is because GDB can't
     440             :    disambiguate a plain call to debug(some_vec), and it must be called
     441             :    like debug<TYPE>(some_vec).  */
     442             : 
     443             : template<typename T>
     444             : void
     445             : debug_helper (vec<T> &ref)
     446             : {
     447             :   unsigned i;
     448             :   for (i = 0; i < ref.length (); ++i)
     449             :     {
     450             :       fprintf (stderr, "[%d] = ", i);
     451             :       debug_slim (ref[i]);
     452             :       fputc ('\n', stderr);
     453             :     }
     454             : }
     455             : 
     456             : /* We need a separate va_gc variant here because default template
     457             :    argument for functions cannot be used in c++-98.  Once this
     458             :    restriction is removed, those variant should be folded with the
     459             :    above debug_helper.  */
     460             : 
     461             : template<typename T>
     462             : void
     463             : debug_helper (vec<T, va_gc> &ref)
     464             : {
     465             :   unsigned i;
     466             :   for (i = 0; i < ref.length (); ++i)
     467             :     {
     468             :       fprintf (stderr, "[%d] = ", i);
     469             :       debug_slim (ref[i]);
     470             :       fputc ('\n', stderr);
     471             :     }
     472             : }
     473             : 
     474             : /* Macro to define debug(vec<T>) and debug(vec<T, va_gc>) helper
     475             :    functions for a type T.  */
     476             : 
     477             : #define DEFINE_DEBUG_VEC(T) \
     478             :   template void debug_helper (vec<T> &);              \
     479             :   template void debug_helper (vec<T, va_gc> &);               \
     480             :   /* Define the vec<T> debug functions.  */               \
     481             :   DEBUG_FUNCTION void                                   \
     482             :   debug (vec<T> &ref)                                 \
     483             :   {                                                     \
     484             :     debug_helper <T> (ref);                               \
     485             :   }                                                     \
     486             :   DEBUG_FUNCTION void                                   \
     487             :   debug (vec<T> *ptr)                                     \
     488             :   {                                                     \
     489             :     if (ptr)                                            \
     490             :       debug (*ptr);                                     \
     491             :     else                                                \
     492             :       fprintf (stderr, "<nil>\n");                      \
     493             :   }                                                     \
     494             :   /* Define the vec<T, va_gc> debug functions.  */        \
     495             :   DEBUG_FUNCTION void                                   \
     496             :   debug (vec<T, va_gc> &ref)                          \
     497             :   {                                                     \
     498             :     debug_helper <T> (ref);                               \
     499             :   }                                                     \
     500             :   DEBUG_FUNCTION void                                   \
     501             :   debug (vec<T, va_gc> *ptr)                              \
     502             :   {                                                     \
     503             :     if (ptr)                                            \
     504             :       debug (*ptr);                                     \
     505             :     else                                                \
     506             :       fprintf (stderr, "<nil>\n");                      \
     507             :   }
     508             : 
     509             : /* Default-construct N elements in DST.  */
     510             : 
     511             : template <typename T>
     512             : inline void
     513     7810173 : vec_default_construct (T *dst, unsigned n)
     514             : {
     515             : #ifdef BROKEN_VALUE_INITIALIZATION
     516             :   /* Versions of GCC before 4.4 sometimes leave certain objects
     517             :      uninitialized when value initialized, though if the type has
     518             :      user defined default ctor, that ctor is invoked.  As a workaround
     519             :      perform clearing first and then the value initialization, which
     520             :      fixes the case when value initialization doesn't initialize due to
     521             :      the bugs and should initialize to all zeros, but still allows
     522             :      vectors for types with user defined default ctor that initializes
     523             :      some or all elements to non-zero.  If T has no user defined
     524             :      default ctor and some non-static data members have user defined
     525             :      default ctors that initialize to non-zero the workaround will
     526             :      still not work properly; in that case we just need to provide
     527             :      user defined default ctor.  */
     528             :   memset (dst, '\0', sizeof (T) * n);
     529             : #endif
     530    40994396 :   for ( ; n; ++dst, --n)
     531    33184223 :     ::new (static_cast<void*>(dst)) T ();
     532             : }
     533             : 
     534             : /* Copy-construct N elements in DST from *SRC.  */
     535             : 
     536             : template <typename T>
     537             : inline void
     538     1883513 : vec_copy_construct (T *dst, const T *src, unsigned n)
     539             : {
     540     7651322 :   for ( ; n; ++dst, ++src, --n)
     541     5767809 :     ::new (static_cast<void*>(dst)) T (*src);
     542             : }
     543             : 
     544             : /* Type to provide zero-initialized values for vec<T, A, L>.  This is
     545             :    used to  provide nil initializers for vec instances.  Since vec must
     546             :    be a trivially copyable type that can be copied by memcpy and zeroed
     547             :    out by memset, it must have defaulted default and copy ctor and copy
     548             :    assignment.  To initialize a vec either use value initialization
     549             :    (e.g., vec() or vec v{ };) or assign it the value vNULL.  This isn't
     550             :    needed for file-scope and function-local static vectors, which are
     551             :    zero-initialized by default.  */
     552             : struct vnull { };
     553             : constexpr vnull vNULL{ };
     554             : 
     555             : 
     556             : /* Embeddable vector.  These vectors are suitable to be embedded
     557             :    in other data structures so that they can be pre-allocated in a
     558             :    contiguous memory block.
     559             : 
     560             :    Embeddable vectors are implemented using the trailing array idiom,
     561             :    thus they are not resizeable without changing the address of the
     562             :    vector object itself.  This means you cannot have variables or
     563             :    fields of embeddable vector type -- always use a pointer to a
     564             :    vector.  The one exception is the final field of a structure, which
     565             :    could be a vector type.
     566             : 
     567             :    You will have to use the embedded_size & embedded_init calls to
     568             :    create such objects, and they will not be resizeable (so the 'safe'
     569             :    allocation variants are not available).
     570             : 
     571             :    Properties:
     572             : 
     573             :         - The whole vector and control data are allocated in a single
     574             :           contiguous block.  It uses the trailing-vector idiom, so
     575             :           allocation must reserve enough space for all the elements
     576             :           in the vector plus its control data.
     577             :         - The vector cannot be re-allocated.
     578             :         - The vector cannot grow nor shrink.
     579             :         - No indirections needed for access/manipulation.
     580             :         - It requires 2 words of storage (prior to vector allocation).  */
     581             : 
     582             : template<typename T, typename A>
     583             : struct GTY((user)) vec<T, A, vl_embed>
     584             : {
     585             : public:
     586    14317178 :   unsigned allocated (void) const { return m_vecpfx.m_alloc; }
     587  4119427636 :   unsigned length (void) const { return m_vecpfx.m_num; }
     588   801983692 :   bool is_empty (void) const { return m_vecpfx.m_num == 0; }
     589    92603648 :   T *address (void) { return reinterpret_cast <T *> (this + 1); }
     590    51283837 :   const T *address (void) const
     591    51283837 :     { return reinterpret_cast <const T *> (this + 1); }
     592     9597516 :   T *begin () { return address (); }
     593    49611073 :   const T *begin () const { return address (); }
     594    29773321 :   T *end () { return address () + length (); }
     595    49611073 :   const T *end () const { return address () + length (); }
     596             :   const T &operator[] (unsigned) const;
     597             :   T &operator[] (unsigned);
     598             :   T &last (void);
     599             :   bool space (unsigned) const;
     600             :   bool iterate (unsigned, T *) const;
     601             :   bool iterate (unsigned, T **) const;
     602             :   vec *copy (ALONE_CXX_MEM_STAT_INFO) const;
     603             :   void splice (const vec &);
     604             :   void splice (const vec *src);
     605             :   T *quick_push (const T &);
     606             :   T &pop (void);
     607             :   void truncate (unsigned);
     608             :   void quick_insert (unsigned, const T &);
     609             :   void ordered_remove (unsigned);
     610             :   void unordered_remove (unsigned);
     611             :   void block_remove (unsigned, unsigned);
     612             :   void qsort (int (*) (const void *, const void *));
     613             :   void sort (int (*) (const void *, const void *, void *), void *);
     614             :   void stablesort (int (*) (const void *, const void *, void *), void *);
     615             :   T *bsearch (const void *key, int (*compar) (const void *, const void *));
     616             :   T *bsearch (const void *key,
     617             :               int (*compar)(const void *, const void *, void *), void *);
     618             :   unsigned lower_bound (const T &, bool (*) (const T &, const T &)) const;
     619             :   bool contains (const T &search) const;
     620             :   static size_t embedded_size (unsigned);
     621             :   void embedded_init (unsigned, unsigned = 0, unsigned = 0);
     622             :   void quick_grow (unsigned len);
     623             :   void quick_grow_cleared (unsigned len);
     624             : 
     625             :   /* vec class can access our internal data and functions.  */
     626             :   template <typename, typename, typename> friend struct vec;
     627             : 
     628             :   /* The allocator types also need access to our internals.  */
     629             :   friend struct va_gc;
     630             :   friend struct va_gc_atomic;
     631             :   friend struct va_heap;
     632             : 
     633             :   /* FIXME - This field should be private, but we need to cater to
     634             :              compilers that have stricter notions of PODness for types.  */
     635             :   /* Align m_vecpfx to simplify address ().  */
     636             :   alignas (T) alignas (vec_prefix) vec_prefix m_vecpfx;
     637             : };
     638             : 
     639             : 
     640             : /* Convenience wrapper functions to use when dealing with pointers to
     641             :    embedded vectors.  Some functionality for these vectors must be
     642             :    provided via free functions for these reasons:
     643             : 
     644             :         1- The pointer may be NULL (e.g., before initial allocation).
     645             : 
     646             :         2- When the vector needs to grow, it must be reallocated, so
     647             :            the pointer will change its value.
     648             : 
     649             :    Because of limitations with the current GC machinery, all vectors
     650             :    in GC memory *must* be pointers.  */
     651             : 
     652             : 
     653             : /* If V contains no room for NELEMS elements, return false. Otherwise,
     654             :    return true.  */
     655             : template<typename T, typename A>
     656             : inline bool
     657 24121728307 : vec_safe_space (const vec<T, A, vl_embed> *v, unsigned nelems)
     658             : {
     659 47940527181 :   return v ? v->space (nelems) : nelems == 0;
     660             : }
     661             : 
     662             : 
     663             : /* If V is NULL, return 0.  Otherwise, return V->length().  */
     664             : template<typename T, typename A>
     665             : inline unsigned
     666  3499722743 : vec_safe_length (const vec<T, A, vl_embed> *v)
     667             : {
     668  3497166754 :   return v ? v->length () : 0;
     669             : }
     670             : 
     671             : 
     672             : /* If V is NULL, return NULL.  Otherwise, return V->address().  */
     673             : template<typename T, typename A>
     674             : inline T *
     675     5463538 : vec_safe_address (vec<T, A, vl_embed> *v)
     676             : {
     677     5463538 :   return v ? v->address () : NULL;
     678             : }
     679             : 
     680             : 
     681             : /* If V is NULL, return true.  Otherwise, return V->is_empty().  */
     682             : template<typename T, typename A>
     683             : inline bool
     684   859455713 : vec_safe_is_empty (vec<T, A, vl_embed> *v)
     685             : {
     686   859455713 :   return v ? v->is_empty () : true;
     687             : }
     688             : 
     689             : /* If V does not have space for NELEMS elements, call
     690             :    V->reserve(NELEMS, EXACT).  */
     691             : template<typename T, typename A>
     692             : inline bool
     693 24122711682 : vec_safe_reserve (vec<T, A, vl_embed> *&v, unsigned nelems, bool exact = false
     694             :                   CXX_MEM_STAT_INFO)
     695             : {
     696 47941510556 :   bool extend = nelems ? !vec_safe_space (v, nelems) : false;
     697             :   if (extend)
     698   343347778 :     A::reserve (v, nelems, exact PASS_MEM_STAT);
     699 24122711682 :   return extend;
     700             : }
     701             : 
     702             : template<typename T, typename A>
     703             : inline bool
     704   128019061 : vec_safe_reserve_exact (vec<T, A, vl_embed> *&v, unsigned nelems
     705             :                         CXX_MEM_STAT_INFO)
     706             : {
     707    26181993 :   return vec_safe_reserve (v, nelems, true PASS_MEM_STAT);
     708             : }
     709             : 
     710             : 
     711             : /* Allocate GC memory for V with space for NELEMS slots.  If NELEMS
     712             :    is 0, V is initialized to NULL.  */
     713             : 
     714             : template<typename T, typename A>
     715             : inline void
     716    40945825 : vec_alloc (vec<T, A, vl_embed> *&v, unsigned nelems CXX_MEM_STAT_INFO)
     717             : {
     718    39127920 :   v = NULL;
     719    40856565 :   vec_safe_reserve (v, nelems, false PASS_MEM_STAT);
     720         569 : }
     721             : 
     722             : 
     723             : /* Free the GC memory allocated by vector V and set it to NULL.  */
     724             : 
     725             : template<typename T, typename A>
     726             : inline void
     727      446549 : vec_free (vec<T, A, vl_embed> *&v)
     728             : {
     729    11268517 :   A::release (v);
     730       89898 : }
     731             : 
     732             : 
     733             : /* Grow V to length LEN.  Allocate it, if necessary.  */
     734             : template<typename T, typename A>
     735             : inline void
     736     2165569 : vec_safe_grow (vec<T, A, vl_embed> *&v, unsigned len,
     737             :                bool exact = false CXX_MEM_STAT_INFO)
     738             : {
     739     2165569 :   unsigned oldlen = vec_safe_length (v);
     740      470895 :   gcc_checking_assert (len >= oldlen);
     741     2165569 :   vec_safe_reserve (v, len - oldlen, exact PASS_MEM_STAT);
     742     2165569 :   v->quick_grow (len);
     743     2165569 : }
     744             : 
     745             : 
     746             : /* If V is NULL, allocate it.  Call V->safe_grow_cleared(LEN).  */
     747             : template<typename T, typename A>
     748             : inline void
     749      330394 : vec_safe_grow_cleared (vec<T, A, vl_embed> *&v, unsigned len,
     750             :                        bool exact = false CXX_MEM_STAT_INFO)
     751             : {
     752      330394 :   unsigned oldlen = vec_safe_length (v);
     753      330394 :   vec_safe_grow (v, len, exact PASS_MEM_STAT);
     754      330394 :   vec_default_construct (v->address () + oldlen, len - oldlen);
     755      330394 : }
     756             : 
     757             : 
     758             : /* Assume V is not NULL.  */
     759             : 
     760             : template<typename T>
     761             : inline void
     762             : vec_safe_grow_cleared (vec<T, va_heap, vl_ptr> *&v,
     763             :                        unsigned len, bool exact = false CXX_MEM_STAT_INFO)
     764             : {
     765             :   v->safe_grow_cleared (len, exact PASS_MEM_STAT);
     766             : }
     767             : 
     768             : /* If V does not have space for NELEMS elements, call
     769             :    V->reserve(NELEMS, EXACT).  */
     770             : 
     771             : template<typename T>
     772             : inline bool
     773             : vec_safe_reserve (vec<T, va_heap, vl_ptr> *&v, unsigned nelems, bool exact = false
     774             :                   CXX_MEM_STAT_INFO)
     775             : {
     776             :   return v->reserve (nelems, exact);
     777             : }
     778             : 
     779             : 
     780             : /* If V is NULL return false, otherwise return V->iterate(IX, PTR).  */
     781             : template<typename T, typename A>
     782             : inline bool
     783  6768134205 : vec_safe_iterate (const vec<T, A, vl_embed> *v, unsigned ix, T **ptr)
     784             : {
     785  6678152349 :   if (v)
     786   751339026 :     return v->iterate (ix, ptr);
     787             :   else
     788             :     {
     789             :       *ptr = 0;
     790             :       return false;
     791             :     }
     792             : }
     793             : 
     794             : template<typename T, typename A>
     795             : inline bool
     796  3944677874 : vec_safe_iterate (const vec<T, A, vl_embed> *v, unsigned ix, T *ptr)
     797             : {
     798  3920162565 :   if (v)
     799  1175327612 :     return v->iterate (ix, ptr);
     800             :   else
     801             :     {
     802          10 :       *ptr = 0;
     803          10 :       return false;
     804             :     }
     805             : }
     806             : 
     807             : 
     808             : /* If V has no room for one more element, reallocate it.  Then call
     809             :    V->quick_push(OBJ).  */
     810             : template<typename T, typename A>
     811             : inline T *
     812 23937842424 : vec_safe_push (vec<T, A, vl_embed> *&v, const T &obj CXX_MEM_STAT_INFO)
     813             : {
     814 23937842424 :   vec_safe_reserve (v, 1, false PASS_MEM_STAT);
     815 23937842424 :   return v->quick_push (obj);
     816             : }
     817             : 
     818             : 
     819             : /* if V has no room for one more element, reallocate it.  Then call
     820             :    V->quick_insert(IX, OBJ).  */
     821             : template<typename T, typename A>
     822             : inline void
     823     1477059 : vec_safe_insert (vec<T, A, vl_embed> *&v, unsigned ix, const T &obj
     824             :                  CXX_MEM_STAT_INFO)
     825             : {
     826     1477059 :   vec_safe_reserve (v, 1, false PASS_MEM_STAT);
     827     1477059 :   v->quick_insert (ix, obj);
     828     1477059 : }
     829             : 
     830             : 
     831             : /* If V is NULL, do nothing.  Otherwise, call V->truncate(SIZE).  */
     832             : template<typename T, typename A>
     833             : inline void
     834   337484842 : vec_safe_truncate (vec<T, A, vl_embed> *v, unsigned size)
     835             : {
     836   337484316 :   if (v)
     837   261124499 :     v->truncate (size);
     838         526 : }
     839             : 
     840             : 
     841             : /* If SRC is not NULL, return a pointer to a copy of it.  */
     842             : template<typename T, typename A>
     843             : inline vec<T, A, vl_embed> *
     844     6578431 : vec_safe_copy (vec<T, A, vl_embed> *src CXX_MEM_STAT_INFO)
     845             : {
     846     6578431 :   return src ? src->copy (ALONE_PASS_MEM_STAT) : NULL;
     847             : }
     848             : 
     849             : /* Copy the elements from SRC to the end of DST as if by memcpy.
     850             :    Reallocate DST, if necessary.  */
     851             : template<typename T, typename A>
     852             : inline void
     853          16 : vec_safe_splice (vec<T, A, vl_embed> *&dst, const vec<T, A, vl_embed> *src
     854             :                  CXX_MEM_STAT_INFO)
     855             : {
     856          32 :   unsigned src_len = vec_safe_length (src);
     857          16 :   if (src_len)
     858             :     {
     859          32 :       vec_safe_reserve_exact (dst, vec_safe_length (dst) + src_len
     860             :                               PASS_MEM_STAT);
     861          16 :       dst->splice (*src);
     862             :     }
     863          16 : }
     864             : 
     865             : /* Return true if SEARCH is an element of V.  Note that this is O(N) in the
     866             :    size of the vector and so should be used with care.  */
     867             : 
     868             : template<typename T, typename A>
     869             : inline bool
     870             : vec_safe_contains (vec<T, A, vl_embed> *v, const T &search)
     871             : {
     872             :   return v ? v->contains (search) : false;
     873             : }
     874             : 
     875             : /* Index into vector.  Return the IX'th element.  IX must be in the
     876             :    domain of the vector.  */
     877             : 
     878             : template<typename T, typename A>
     879             : inline const T &
     880   235130857 : vec<T, A, vl_embed>::operator[] (unsigned ix) const
     881             : {
     882   235130857 :   gcc_checking_assert (ix < m_vecpfx.m_num);
     883   235130857 :   return address ()[ix];
     884             : }
     885             : 
     886             : template<typename T, typename A>
     887             : inline T &
     888 78738896509 : vec<T, A, vl_embed>::operator[] (unsigned ix)
     889             : {
     890 78738896509 :   gcc_checking_assert (ix < m_vecpfx.m_num);
     891 78738896509 :   return address ()[ix];
     892             : }
     893             : 
     894             : 
     895             : /* Get the final element of the vector, which must not be empty.  */
     896             : 
     897             : template<typename T, typename A>
     898             : inline T &
     899 12567057124 : vec<T, A, vl_embed>::last (void)
     900             : {
     901 12567057124 :   gcc_checking_assert (m_vecpfx.m_num > 0);
     902 12567057124 :   return (*this)[m_vecpfx.m_num - 1];
     903             : }
     904             : 
     905             : 
     906             : /* If this vector has space for NELEMS additional entries, return
     907             :    true.  You usually only need to use this if you are doing your
     908             :    own vector reallocation, for instance on an embedded vector.  This
     909             :    returns true in exactly the same circumstances that vec::reserve
     910             :    will.  */
     911             : 
     912             : template<typename T, typename A>
     913             : inline bool
     914 76768113782 : vec<T, A, vl_embed>::space (unsigned nelems) const
     915             : {
     916 23818803589 :   return m_vecpfx.m_alloc - m_vecpfx.m_num >= nelems;
     917             : }
     918             : 
     919             : 
     920             : /* Return iteration condition and update *PTR to (a copy of) the IX'th
     921             :    element of this vector.  Use this to iterate over the elements of a
     922             :    vector as follows,
     923             : 
     924             :      for (ix = 0; v->iterate (ix, &val); ix++)
     925             :        continue;  */
     926             : 
     927             : template<typename T, typename A>
     928             : inline bool
     929 10882519848 : vec<T, A, vl_embed>::iterate (unsigned ix, T *ptr) const
     930             : {
     931 10367634751 :   if (ix < m_vecpfx.m_num)
     932             :     {
     933  4852887493 :       *ptr = address ()[ix];
     934       26424 :       return true;
     935             :     }
     936             :   else
     937             :     {
     938     1753515 :       *ptr = 0;
     939       13124 :       return false;
     940             :     }
     941             : }
     942             : 
     943             : 
     944             : /* Return iteration condition and update *PTR to point to the
     945             :    IX'th element of this vector.  Use this to iterate over the
     946             :    elements of a vector as follows,
     947             : 
     948             :      for (ix = 0; v->iterate (ix, &ptr); ix++)
     949             :        continue;
     950             : 
     951             :    This variant is for vectors of objects.  */
     952             : 
     953             : template<typename T, typename A>
     954             : inline bool
     955  2144969075 : vec<T, A, vl_embed>::iterate (unsigned ix, T **ptr) const
     956             : {
     957  2144962054 :   if (ix < m_vecpfx.m_num)
     958             :     {
     959  1623204124 :       *ptr = CONST_CAST (T *, &address ()[ix]);
     960           0 :       return true;
     961             :     }
     962             :   else
     963             :     {
     964             :       *ptr = 0;
     965             :       return false;
     966             :     }
     967             : }
     968             : 
     969             : 
     970             : /* Return a pointer to a copy of this vector.  */
     971             : 
     972             : template<typename T, typename A>
     973             : inline vec<T, A, vl_embed> *
     974     1818837 : vec<T, A, vl_embed>::copy (ALONE_MEM_STAT_DECL) const
     975             : {
     976     1818837 :   vec<T, A, vl_embed> *new_vec = NULL;
     977     1818837 :   unsigned len = length ();
     978     1818837 :   if (len)
     979             :     {
     980     1672748 :       vec_alloc (new_vec, len PASS_MEM_STAT);
     981     1672748 :       new_vec->embedded_init (len, len);
     982     3491585 :       vec_copy_construct (new_vec->address (), address (), len);
     983             :     }
     984     1818837 :   return new_vec;
     985             : }
     986             : 
     987             : 
     988             : /* Copy the elements from SRC to the end of this vector as if by memcpy.
     989             :    The vector must have sufficient headroom available.  */
     990             : 
     991             : template<typename T, typename A>
     992             : inline void
     993          16 : vec<T, A, vl_embed>::splice (const vec<T, A, vl_embed> &src)
     994             : {
     995          16 :   unsigned len = src.length ();
     996          16 :   if (len)
     997             :     {
     998          16 :       gcc_checking_assert (space (len));
     999          16 :       vec_copy_construct (end (), src.address (), len);
    1000          16 :       m_vecpfx.m_num += len;
    1001             :     }
    1002          16 : }
    1003             : 
    1004             : template<typename T, typename A>
    1005             : inline void
    1006             : vec<T, A, vl_embed>::splice (const vec<T, A, vl_embed> *src)
    1007             : {
    1008             :   if (src)
    1009             :     splice (*src);
    1010             : }
    1011             : 
    1012             : 
    1013             : /* Push OBJ (a new element) onto the end of the vector.  There must be
    1014             :    sufficient space in the vector.  Return a pointer to the slot
    1015             :    where OBJ was inserted.  */
    1016             : 
    1017             : template<typename T, typename A>
    1018             : inline T *
    1019 38737198702 : vec<T, A, vl_embed>::quick_push (const T &obj)
    1020             : {
    1021 38737198702 :   gcc_checking_assert (space (1));
    1022 38737198702 :   T *slot = &address ()[m_vecpfx.m_num++];
    1023 38737198702 :   *slot = obj;
    1024 38737198702 :   return slot;
    1025             : }
    1026             : 
    1027             : 
    1028             : /* Pop and return the last element off the end of the vector.  */
    1029             : 
    1030             : template<typename T, typename A>
    1031             : inline T &
    1032 30881568656 : vec<T, A, vl_embed>::pop (void)
    1033             : {
    1034 30881568656 :   gcc_checking_assert (length () > 0);
    1035 30881568656 :   return address ()[--m_vecpfx.m_num];
    1036             : }
    1037             : 
    1038             : 
    1039             : /* Set the length of the vector to SIZE.  The new length must be less
    1040             :    than or equal to the current length.  This is an O(1) operation.  */
    1041             : 
    1042             : template<typename T, typename A>
    1043             : inline void
    1044   368273097 : vec<T, A, vl_embed>::truncate (unsigned size)
    1045             : {
    1046   368273097 :   gcc_checking_assert (length () >= size);
    1047   368273097 :   m_vecpfx.m_num = size;
    1048   368273097 : }
    1049             : 
    1050             : 
    1051             : /* Insert an element, OBJ, at the IXth position of this vector.  There
    1052             :    must be sufficient space.  */
    1053             : 
    1054             : template<typename T, typename A>
    1055             : inline void
    1056    14317178 : vec<T, A, vl_embed>::quick_insert (unsigned ix, const T &obj)
    1057             : {
    1058    14317178 :   gcc_checking_assert (length () < allocated ());
    1059    14317178 :   gcc_checking_assert (ix <= length ());
    1060    14317178 :   T *slot = &address ()[ix];
    1061    14317178 :   memmove (slot + 1, slot, (m_vecpfx.m_num++ - ix) * sizeof (T));
    1062    14317178 :   *slot = obj;
    1063    14317178 : }
    1064             : 
    1065             : 
    1066             : /* Remove an element from the IXth position of this vector.  Ordering of
    1067             :    remaining elements is preserved.  This is an O(N) operation due to
    1068             :    memmove.  */
    1069             : 
    1070             : template<typename T, typename A>
    1071             : inline void
    1072        3751 : vec<T, A, vl_embed>::ordered_remove (unsigned ix)
    1073             : {
    1074        3751 :   gcc_checking_assert (ix < length ());
    1075        3751 :   T *slot = &address ()[ix];
    1076        3751 :   memmove (slot, slot + 1, (--m_vecpfx.m_num - ix) * sizeof (T));
    1077        3751 : }
    1078             : 
    1079             : 
    1080             : /* Remove elements in [START, END) from VEC for which COND holds.  Ordering of
    1081             :    remaining elements is preserved.  This is an O(N) operation.  */
    1082             : 
    1083             : #define VEC_ORDERED_REMOVE_IF_FROM_TO(vec, read_index, write_index,     \
    1084             :                                       elem_ptr, start, end, cond)       \
    1085             :   {                                                                     \
    1086             :     gcc_assert ((end) <= (vec).length ());                           \
    1087             :     for (read_index = write_index = (start); read_index < (end);     \
    1088             :          ++read_index)                                                  \
    1089             :       {                                                                 \
    1090             :         elem_ptr = &(vec)[read_index];                                      \
    1091             :         bool remove_p = (cond);                                         \
    1092             :         if (remove_p)                                                   \
    1093             :           continue;                                                     \
    1094             :                                                                         \
    1095             :         if (read_index != write_index)                                  \
    1096             :           (vec)[write_index] = (vec)[read_index];                       \
    1097             :                                                                         \
    1098             :         write_index++;                                                  \
    1099             :       }                                                                 \
    1100             :                                                                         \
    1101             :     if (read_index - write_index > 0)                                        \
    1102             :       (vec).block_remove (write_index, read_index - write_index);       \
    1103             :   }
    1104             : 
    1105             : 
    1106             : /* Remove elements from VEC for which COND holds.  Ordering of remaining
    1107             :    elements is preserved.  This is an O(N) operation.  */
    1108             : 
    1109             : #define VEC_ORDERED_REMOVE_IF(vec, read_index, write_index, elem_ptr,   \
    1110             :                               cond)                                     \
    1111             :   VEC_ORDERED_REMOVE_IF_FROM_TO ((vec), read_index, write_index,        \
    1112             :                                  elem_ptr, 0, (vec).length (), (cond))
    1113             : 
    1114             : /* Remove an element from the IXth position of this vector.  Ordering of
    1115             :    remaining elements is destroyed.  This is an O(1) operation.  */
    1116             : 
    1117             : template<typename T, typename A>
    1118             : inline void
    1119      434313 : vec<T, A, vl_embed>::unordered_remove (unsigned ix)
    1120             : {
    1121      434313 :   gcc_checking_assert (ix < length ());
    1122      434313 :   T *p = address ();
    1123      434313 :   p[ix] = p[--m_vecpfx.m_num];
    1124      434313 : }
    1125             : 
    1126             : 
    1127             : /* Remove LEN elements starting at the IXth.  Ordering is retained.
    1128             :    This is an O(N) operation due to memmove.  */
    1129             : 
    1130             : template<typename T, typename A>
    1131             : inline void
    1132           1 : vec<T, A, vl_embed>::block_remove (unsigned ix, unsigned len)
    1133             : {
    1134           1 :   gcc_checking_assert (ix + len <= length ());
    1135           1 :   T *slot = &address ()[ix];
    1136           1 :   m_vecpfx.m_num -= len;
    1137           1 :   memmove (slot, slot + len, (m_vecpfx.m_num - ix) * sizeof (T));
    1138           1 : }
    1139             : 
    1140             : 
    1141             : /* Sort the contents of this vector with qsort.  CMP is the comparison
    1142             :    function to pass to qsort.  */
    1143             : 
    1144             : template<typename T, typename A>
    1145             : inline void
    1146    14564625 : vec<T, A, vl_embed>::qsort (int (*cmp) (const void *, const void *))
    1147             : {
    1148    14564625 :   if (length () > 1)
    1149    12945239 :     gcc_qsort (address (), length (), sizeof (T), cmp);
    1150    14564625 : }
    1151             : 
    1152             : /* Sort the contents of this vector with qsort.  CMP is the comparison
    1153             :    function to pass to qsort.  */
    1154             : 
    1155             : template<typename T, typename A>
    1156             : inline void
    1157             : vec<T, A, vl_embed>::sort (int (*cmp) (const void *, const void *, void *),
    1158             :                            void *data)
    1159             : {
    1160             :   if (length () > 1)
    1161             :     gcc_sort_r (address (), length (), sizeof (T), cmp, data);
    1162             : }
    1163             : 
    1164             : /* Sort the contents of this vector with gcc_stablesort_r.  CMP is the
    1165             :    comparison function to pass to qsort.  */
    1166             : 
    1167             : template<typename T, typename A>
    1168             : inline void
    1169             : vec<T, A, vl_embed>::stablesort (int (*cmp) (const void *, const void *,
    1170             :                                              void *), void *data)
    1171             : {
    1172             :   if (length () > 1)
    1173             :     gcc_stablesort_r (address (), length (), sizeof (T), cmp, data);
    1174             : }
    1175             : 
    1176             : /* Search the contents of the sorted vector with a binary search.
    1177             :    CMP is the comparison function to pass to bsearch.  */
    1178             : 
    1179             : template<typename T, typename A>
    1180             : inline T *
    1181             : vec<T, A, vl_embed>::bsearch (const void *key,
    1182             :                               int (*compar) (const void *, const void *))
    1183             : {
    1184             :   const void *base = this->address ();
    1185             :   size_t nmemb = this->length ();
    1186             :   size_t size = sizeof (T);
    1187             :   /* The following is a copy of glibc stdlib-bsearch.h.  */
    1188             :   size_t l, u, idx;
    1189             :   const void *p;
    1190             :   int comparison;
    1191             : 
    1192             :   l = 0;
    1193             :   u = nmemb;
    1194             :   while (l < u)
    1195             :     {
    1196             :       idx = (l + u) / 2;
    1197             :       p = (const void *) (((const char *) base) + (idx * size));
    1198             :       comparison = (*compar) (key, p);
    1199             :       if (comparison < 0)
    1200             :         u = idx;
    1201             :       else if (comparison > 0)
    1202             :         l = idx + 1;
    1203             :       else
    1204             :         return (T *)const_cast<void *>(p);
    1205             :     }
    1206             : 
    1207             :   return NULL;
    1208             : }
    1209             : 
    1210             : /* Search the contents of the sorted vector with a binary search.
    1211             :    CMP is the comparison function to pass to bsearch.  */
    1212             : 
    1213             : template<typename T, typename A>
    1214             : inline T *
    1215             : vec<T, A, vl_embed>::bsearch (const void *key,
    1216             :                               int (*compar) (const void *, const void *,
    1217             :                                              void *), void *data)
    1218             : {
    1219             :   const void *base = this->address ();
    1220             :   size_t nmemb = this->length ();
    1221             :   size_t size = sizeof (T);
    1222             :   /* The following is a copy of glibc stdlib-bsearch.h.  */
    1223             :   size_t l, u, idx;
    1224             :   const void *p;
    1225             :   int comparison;
    1226             : 
    1227             :   l = 0;
    1228             :   u = nmemb;
    1229             :   while (l < u)
    1230             :     {
    1231             :       idx = (l + u) / 2;
    1232             :       p = (const void *) (((const char *) base) + (idx * size));
    1233             :       comparison = (*compar) (key, p, data);
    1234             :       if (comparison < 0)
    1235             :         u = idx;
    1236             :       else if (comparison > 0)
    1237             :         l = idx + 1;
    1238             :       else
    1239             :         return (T *)const_cast<void *>(p);
    1240             :     }
    1241             : 
    1242             :   return NULL;
    1243             : }
    1244             : 
    1245             : /* Return true if SEARCH is an element of V.  Note that this is O(N) in the
    1246             :    size of the vector and so should be used with care.  */
    1247             : 
    1248             : template<typename T, typename A>
    1249             : inline bool
    1250             : vec<T, A, vl_embed>::contains (const T &search) const
    1251             : {
    1252             :   unsigned int len = length ();
    1253             :   const T *p = address ();
    1254             :   for (unsigned int i = 0; i < len; i++)
    1255             :     {
    1256             :       const T *slot = &p[i];
    1257             :       if (*slot == search)
    1258             :         return true;
    1259             :     }
    1260             : 
    1261             :   return false;
    1262             : }
    1263             : 
    1264             : /* Find and return the first position in which OBJ could be inserted
    1265             :    without changing the ordering of this vector.  LESSTHAN is a
    1266             :    function that returns true if the first argument is strictly less
    1267             :    than the second.  */
    1268             : 
    1269             : template<typename T, typename A>
    1270             : unsigned
    1271             : vec<T, A, vl_embed>::lower_bound (const T &obj,
    1272             :                                   bool (*lessthan)(const T &, const T &))
    1273             :   const
    1274             : {
    1275             :   unsigned int len = length ();
    1276             :   unsigned int half, middle;
    1277             :   unsigned int first = 0;
    1278             :   while (len > 0)
    1279             :     {
    1280             :       half = len / 2;
    1281             :       middle = first;
    1282             :       middle += half;
    1283             :       const T &middle_elem = address ()[middle];
    1284             :       if (lessthan (middle_elem, obj))
    1285             :         {
    1286             :           first = middle;
    1287             :           ++first;
    1288             :           len = len - half - 1;
    1289             :         }
    1290             :       else
    1291             :         len = half;
    1292             :     }
    1293             :   return first;
    1294             : }
    1295             : 
    1296             : 
    1297             : /* Return the number of bytes needed to embed an instance of an
    1298             :    embeddable vec inside another data structure.
    1299             : 
    1300             :    Use these methods to determine the required size and initialization
    1301             :    of a vector V of type T embedded within another structure (as the
    1302             :    final member):
    1303             : 
    1304             :    size_t vec<T, A, vl_embed>::embedded_size (unsigned alloc);
    1305             :    void v->embedded_init (unsigned alloc, unsigned num);
    1306             : 
    1307             :    These allow the caller to perform the memory allocation.  */
    1308             : 
    1309             : template<typename T, typename A>
    1310             : inline size_t
    1311   564532833 : vec<T, A, vl_embed>::embedded_size (unsigned alloc)
    1312             : {
    1313             :   struct alignas (T) U { char data[sizeof (T)]; };
    1314             :   typedef vec<U, A, vl_embed> vec_embedded;
    1315             :   typedef typename std::conditional<std::is_standard_layout<T>::value,
    1316             :                                     vec, vec_embedded>::type vec_stdlayout;
    1317             :   static_assert (sizeof (vec_stdlayout) == sizeof (vec), "");
    1318             :   static_assert (alignof (vec_stdlayout) == alignof (vec), "");
    1319   564532833 :   return sizeof (vec_stdlayout) + alloc * sizeof (T);
    1320             : }
    1321             : 
    1322             : 
    1323             : /* Initialize the vector to contain room for ALLOC elements and
    1324             :    NUM active elements.  */
    1325             : 
    1326             : template<typename T, typename A>
    1327             : inline void
    1328  1948403651 : vec<T, A, vl_embed>::embedded_init (unsigned alloc, unsigned num, unsigned aut)
    1329             : {
    1330  1948403651 :   m_vecpfx.m_alloc = alloc;
    1331  1948403651 :   m_vecpfx.m_using_auto_storage = aut;
    1332  1225921088 :   m_vecpfx.m_num = num;
    1333   473335672 : }
    1334             : 
    1335             : 
    1336             : /* Grow the vector to a specific length.  LEN must be as long or longer than
    1337             :    the current length.  The new elements are uninitialized.  */
    1338             : 
    1339             : template<typename T, typename A>
    1340             : inline void
    1341    15365057 : vec<T, A, vl_embed>::quick_grow (unsigned len)
    1342             : {
    1343    15365057 :   gcc_checking_assert (length () <= len && len <= m_vecpfx.m_alloc);
    1344    15365057 :   m_vecpfx.m_num = len;
    1345    15365057 : }
    1346             : 
    1347             : 
    1348             : /* Grow the vector to a specific length.  LEN must be as long or longer than
    1349             :    the current length.  The new elements are initialized to zero.  */
    1350             : 
    1351             : template<typename T, typename A>
    1352             : inline void
    1353      585679 : vec<T, A, vl_embed>::quick_grow_cleared (unsigned len)
    1354             : {
    1355      585679 :   unsigned oldlen = length ();
    1356      585679 :   size_t growby = len - oldlen;
    1357      585679 :   quick_grow (len);
    1358      585679 :   if (growby != 0)
    1359      585679 :     vec_default_construct (address () + oldlen, growby);
    1360      585679 : }
    1361             : 
    1362             : /* Garbage collection support for vec<T, A, vl_embed>.  */
    1363             : 
    1364             : template<typename T>
    1365             : void
    1366   537930235 : gt_ggc_mx (vec<T, va_gc> *v)
    1367             : {
    1368             :   extern void gt_ggc_mx (T &);
    1369 43246333882 :   for (unsigned i = 0; i < v->length (); i++)
    1370 42712369788 :     gt_ggc_mx ((*v)[i]);
    1371   537930235 : }
    1372             : 
    1373             : template<typename T>
    1374             : void
    1375             : gt_ggc_mx (vec<T, va_gc_atomic, vl_embed> *v ATTRIBUTE_UNUSED)
    1376             : {
    1377             :   /* Nothing to do.  Vectors of atomic types wrt GC do not need to
    1378             :      be traversed.  */
    1379             : }
    1380             : 
    1381             : 
    1382             : /* PCH support for vec<T, A, vl_embed>.  */
    1383             : 
    1384             : template<typename T, typename A>
    1385             : void
    1386      213524 : gt_pch_nx (vec<T, A, vl_embed> *v)
    1387             : {
    1388             :   extern void gt_pch_nx (T &);
    1389      552022 :   for (unsigned i = 0; i < v->length (); i++)
    1390      338498 :     gt_pch_nx ((*v)[i]);
    1391      213524 : }
    1392             : 
    1393             : template<typename T>
    1394             : void
    1395             : gt_pch_nx (vec<T, va_gc_atomic, vl_embed> *)
    1396             : {
    1397             :   /* No pointers to note.  */
    1398             : }
    1399             : 
    1400             : template<typename T, typename A>
    1401             : void
    1402       66967 : gt_pch_nx (vec<T *, A, vl_embed> *v, gt_pointer_operator op, void *cookie)
    1403             : {
    1404       92547 :   for (unsigned i = 0; i < v->length (); i++)
    1405       25580 :     op (&((*v)[i]), NULL, cookie);
    1406       66967 : }
    1407             : 
    1408             : template<typename T, typename A>
    1409             : void
    1410        1655 : gt_pch_nx (vec<T, A, vl_embed> *v, gt_pointer_operator op, void *cookie)
    1411             : {
    1412             :   extern void gt_pch_nx (T *, gt_pointer_operator, void *);
    1413        8947 :   for (unsigned i = 0; i < v->length (); i++)
    1414        7292 :     gt_pch_nx (&((*v)[i]), op, cookie);
    1415        1655 : }
    1416             : 
    1417             : template<typename T>
    1418             : void
    1419             : gt_pch_nx (vec<T, va_gc_atomic, vl_embed> *, gt_pointer_operator, void *)
    1420             : {
    1421             :   /* No pointers to note.  */
    1422             : }
    1423             : 
    1424             : 
    1425             : /* Space efficient vector.  These vectors can grow dynamically and are
    1426             :    allocated together with their control data.  They are suited to be
    1427             :    included in data structures.  Prior to initial allocation, they
    1428             :    only take a single word of storage.
    1429             : 
    1430             :    These vectors are implemented as a pointer to an embeddable vector.
    1431             :    The semantics allow for this pointer to be NULL to represent empty
    1432             :    vectors.  This way, empty vectors occupy minimal space in the
    1433             :    structure containing them.
    1434             : 
    1435             :    Properties:
    1436             : 
    1437             :         - The whole vector and control data are allocated in a single
    1438             :           contiguous block.
    1439             :         - The whole vector may be re-allocated.
    1440             :         - Vector data may grow and shrink.
    1441             :         - Access and manipulation requires a pointer test and
    1442             :           indirection.
    1443             :         - It requires 1 word of storage (prior to vector allocation).
    1444             : 
    1445             : 
    1446             :    Limitations:
    1447             : 
    1448             :    These vectors must be PODs because they are stored in unions.
    1449             :    (http://en.wikipedia.org/wiki/Plain_old_data_structures).
    1450             :    As long as we use C++03, we cannot have constructors nor
    1451             :    destructors in classes that are stored in unions.  */
    1452             : 
    1453             : template<typename T, size_t N = 0>
    1454             : class auto_vec;
    1455             : 
    1456             : template<typename T>
    1457             : struct vec<T, va_heap, vl_ptr>
    1458             : {
    1459             : public:
    1460             :   /* Default ctors to ensure triviality.  Use value-initialization
    1461             :      (e.g., vec() or vec v{ };) or vNULL to create a zero-initialized
    1462             :      instance.  */
    1463             :   vec () = default;
    1464             :   vec (const vec &) = default;
    1465             :   /* Initialization from the generic vNULL.  */
    1466     7060290 :   vec (vnull): m_vec () { }
    1467             :   /* Same as default ctor: vec storage must be released manually.  */
    1468             :   ~vec () = default;
    1469             : 
    1470             :   /* Defaulted same as copy ctor.  */
    1471             :   vec& operator= (const vec &) = default;
    1472             : 
    1473             :   /* Prevent implicit conversion from auto_vec.  Use auto_vec::to_vec()
    1474             :      instead.  */
    1475             :   template <size_t N>
    1476             :   vec (auto_vec<T, N> &) = delete;
    1477             : 
    1478             :   template <size_t N>
    1479             :   void operator= (auto_vec<T, N> &) = delete;
    1480             : 
    1481             :   /* Memory allocation and deallocation for the embedded vector.
    1482             :      Needed because we cannot have proper ctors/dtors defined.  */
    1483             :   void create (unsigned nelems CXX_MEM_STAT_INFO);
    1484             :   void release (void);
    1485             : 
    1486             :   /* Vector operations.  */
    1487        3938 :   bool exists (void) const
    1488        3938 :   { return m_vec != NULL; }
    1489             : 
    1490   896418760 :   bool is_empty (void) const
    1491   894635748 :   { return m_vec ? m_vec->is_empty () : true; }
    1492             : 
    1493             :   unsigned allocated (void) const
    1494             :   { return m_vec ? m_vec->allocated () : 0; }
    1495             : 
    1496  5265664786 :   unsigned length (void) const
    1497  5340572612 :   { return m_vec ? m_vec->length () : 0; }
    1498             : 
    1499   281026934 :   T *address (void)
    1500    20915055 :   { return m_vec ? m_vec->address () : NULL; }
    1501             : 
    1502        1880 :   const T *address (void) const
    1503           0 :   { return m_vec ? m_vec->address () : NULL; }
    1504             : 
    1505   159133896 :   T *begin () { return address (); }
    1506             :   const T *begin () const { return address (); }
    1507   129019780 :   T *end () { return begin () + length (); }
    1508             :   const T *end () const { return begin () + length (); }
    1509        2018 :   const T &operator[] (unsigned ix) const
    1510        2018 :   { return (*m_vec)[ix]; }
    1511             : 
    1512             :   bool operator!=(const vec &other) const
    1513             :   { return !(*this == other); }
    1514             : 
    1515        1880 :   bool operator==(const vec &other) const
    1516        1880 :   { return address () == other.address (); }
    1517             : 
    1518  1477370485 :   T &operator[] (unsigned ix)
    1519  1477056721 :   { return (*m_vec)[ix]; }
    1520             : 
    1521        4362 :   T &last (void)
    1522        4362 :   { return m_vec->last (); }
    1523             : 
    1524 14285562065 :   bool space (int nelems) const
    1525 14285562065 :   { return m_vec ? m_vec->space (nelems) : nelems == 0; }
    1526             : 
    1527             :   bool iterate (unsigned ix, T *p) const;
    1528             :   bool iterate (unsigned ix, T **p) const;
    1529             :   vec copy (ALONE_CXX_MEM_STAT_INFO) const;
    1530             :   bool reserve (unsigned, bool = false CXX_MEM_STAT_INFO);
    1531             :   bool reserve_exact (unsigned CXX_MEM_STAT_INFO);
    1532             :   void splice (const vec &);
    1533             :   void safe_splice (const vec & CXX_MEM_STAT_INFO);
    1534             :   T *quick_push (const T &);
    1535             :   T *safe_push (const T &CXX_MEM_STAT_INFO);
    1536             :   T &pop (void);
    1537             :   void truncate (unsigned);
    1538             :   void safe_grow (unsigned, bool = false CXX_MEM_STAT_INFO);
    1539             :   void safe_grow_cleared (unsigned, bool = false CXX_MEM_STAT_INFO);
    1540             :   void quick_grow (unsigned);
    1541             :   void quick_grow_cleared (unsigned);
    1542             :   void quick_insert (unsigned, const T &);
    1543             :   void safe_insert (unsigned, const T & CXX_MEM_STAT_INFO);
    1544             :   void ordered_remove (unsigned);
    1545             :   void unordered_remove (unsigned);
    1546             :   void block_remove (unsigned, unsigned);
    1547             :   void qsort (int (*) (const void *, const void *));
    1548             :   void sort (int (*) (const void *, const void *, void *), void *);
    1549             :   void stablesort (int (*) (const void *, const void *, void *), void *);
    1550             :   T *bsearch (const void *key, int (*compar)(const void *, const void *));
    1551             :   T *bsearch (const void *key,
    1552             :               int (*compar)(const void *, const void *, void *), void *);
    1553             :   unsigned lower_bound (T, bool (*)(const T &, const T &)) const;
    1554             :   bool contains (const T &search) const;
    1555             :   void reverse (void);
    1556             : 
    1557             :   bool using_auto_storage () const;
    1558             : 
    1559             :   /* FIXME - This field should be private, but we need to cater to
    1560             :              compilers that have stricter notions of PODness for types.  */
    1561             :   vec<T, va_heap, vl_embed> *m_vec;
    1562             : };
    1563             : 
    1564             : 
    1565             : /* auto_vec is a subclass of vec that automatically manages creating and
    1566             :    releasing the internal vector. If N is non zero then it has N elements of
    1567             :    internal storage.  The default is no internal storage, and you probably only
    1568             :    want to ask for internal storage for vectors on the stack because if the
    1569             :    size of the vector is larger than the internal storage that space is wasted.
    1570             :    */
    1571             : template<typename T, size_t N /* = 0 */>
    1572             : class auto_vec : public vec<T, va_heap>
    1573             : {
    1574             : public:
    1575  1382195712 :   auto_vec ()
    1576             :   {
    1577  1382195712 :     m_auto.embedded_init (N, 0, 1);
    1578             :     /* ???  Instead of initializing m_vec from &m_auto directly use an
    1579             :        expression that avoids refering to a specific member of 'this'
    1580             :        to derail the -Wstringop-overflow diagnostic code, avoiding
    1581             :        the impression that data accesses are supposed to be to the
    1582             :        m_auto member storage.  */
    1583  1382195712 :     size_t off = (char *) &m_auto - (char *) this;
    1584  1005327869 :     this->m_vec = (vec<T, va_heap, vl_embed> *) ((char *) this + off);
    1585   127040404 :   }
    1586             : 
    1587        2358 :   auto_vec (size_t s CXX_MEM_STAT_INFO)
    1588             :   {
    1589        2358 :     if (s > N)
    1590             :       {
    1591           0 :         this->create (s PASS_MEM_STAT);
    1592           0 :         return;
    1593             :       }
    1594             : 
    1595        2358 :     m_auto.embedded_init (N, 0, 1);
    1596             :     /* ???  See above.  */
    1597        2358 :     size_t off = (char *) &m_auto - (char *) this;
    1598        2358 :     this->m_vec = (vec<T, va_heap, vl_embed> *) ((char *) this + off);
    1599             :   }
    1600             : 
    1601  1382304975 :   ~auto_vec ()
    1602             :   {
    1603  1382176502 :     this->release ();
    1604  1253080517 :   }
    1605             : 
    1606             :   /* Explicitly convert to the base class.  There is no conversion
    1607             :      from a const auto_vec because a copy of the returned vec can
    1608             :      be used to modify *THIS.
    1609             :      This is a legacy function not to be used in new code.  */
    1610             :   vec<T, va_heap> to_vec_legacy () {
    1611             :     return *static_cast<vec<T, va_heap> *>(this);
    1612             :   }
    1613             : 
    1614             : private:
    1615             :   vec<T, va_heap, vl_embed> m_auto;
    1616             :   unsigned char m_data[sizeof (T) * N];
    1617             : };
    1618             : 
    1619             : /* auto_vec is a sub class of vec whose storage is released when it is
    1620             :   destroyed. */
    1621             : template<typename T>
    1622             : class auto_vec<T, 0> : public vec<T, va_heap>
    1623             : {
    1624             : public:
    1625   452572260 :   auto_vec () { this->m_vec = NULL; }
    1626      585679 :   auto_vec (size_t n CXX_MEM_STAT_INFO) { this->create (n PASS_MEM_STAT); }
    1627   453213394 :   ~auto_vec () { this->release (); }
    1628             : 
    1629             :   auto_vec (vec<T, va_heap>&& r)
    1630             :     {
    1631             :       gcc_assert (!r.using_auto_storage ());
    1632             :       this->m_vec = r.m_vec;
    1633             :       r.m_vec = NULL;
    1634             :     }
    1635             : 
    1636       59138 :   auto_vec (auto_vec<T> &&r)
    1637             :     {
    1638           0 :       gcc_assert (!r.using_auto_storage ());
    1639       59138 :       this->m_vec = r.m_vec;
    1640       59138 :       r.m_vec = NULL;
    1641       59138 :     }
    1642             : 
    1643             :   auto_vec& operator= (vec<T, va_heap>&& r)
    1644             :     {
    1645             :             if (this == &r)
    1646             :                     return *this;
    1647             : 
    1648             :       gcc_assert (!r.using_auto_storage ());
    1649             :       this->release ();
    1650             :       this->m_vec = r.m_vec;
    1651             :       r.m_vec = NULL;
    1652             :       return *this;
    1653             :     }
    1654             : 
    1655             :   auto_vec& operator= (auto_vec<T> &&r)
    1656             :     {
    1657             :             if (this == &r)
    1658             :                     return *this;
    1659             : 
    1660             :       gcc_assert (!r.using_auto_storage ());
    1661             :       this->release ();
    1662             :       this->m_vec = r.m_vec;
    1663             :       r.m_vec = NULL;
    1664             :       return *this;
    1665             :     }
    1666             : 
    1667             :   /* Explicitly convert to the base class.  There is no conversion
    1668             :      from a const auto_vec because a copy of the returned vec can
    1669             :      be used to modify *THIS.
    1670             :      This is a legacy function not to be used in new code.  */
    1671             :   vec<T, va_heap> to_vec_legacy () {
    1672             :     return *static_cast<vec<T, va_heap> *>(this);
    1673             :   }
    1674             : 
    1675             :   // You probably don't want to copy a vector, so these are deleted to prevent
    1676             :   // unintentional use.  If you really need a copy of the vectors contents you
    1677             :   // can use copy ().
    1678             :   auto_vec(const auto_vec &) = delete;
    1679             :   auto_vec &operator= (const auto_vec &) = delete;
    1680             : };
    1681             : 
    1682             : 
    1683             : /* Allocate heap memory for pointer V and create the internal vector
    1684             :    with space for NELEMS elements.  If NELEMS is 0, the internal
    1685             :    vector is initialized to empty.  */
    1686             : 
    1687             : template<typename T>
    1688             : inline void
    1689      107621 : vec_alloc (vec<T> *&v, unsigned nelems CXX_MEM_STAT_INFO)
    1690             : {
    1691      107621 :   v = new vec<T>;
    1692      107621 :   v->create (nelems PASS_MEM_STAT);
    1693      107621 : }
    1694             : 
    1695             : 
    1696             : /* A subclass of auto_vec <char *> that frees all of its elements on
    1697             :    deletion.  */
    1698             : 
    1699             : class auto_string_vec : public auto_vec <char *>
    1700             : {
    1701             :  public:
    1702             :   ~auto_string_vec ();
    1703             : };
    1704             : 
    1705             : /* A subclass of auto_vec <T *> that deletes all of its elements on
    1706             :    destruction.
    1707             : 
    1708             :    This is a crude way for a vec to "own" the objects it points to
    1709             :    and clean up automatically.
    1710             : 
    1711             :    For example, no attempt is made to delete elements when an item
    1712             :    within the vec is overwritten.
    1713             : 
    1714             :    We can't rely on gnu::unique_ptr within a container,
    1715             :    since we can't rely on move semantics in C++98.  */
    1716             : 
    1717             : template <typename T>
    1718             : class auto_delete_vec : public auto_vec <T *>
    1719             : {
    1720             :  public:
    1721           0 :   auto_delete_vec () {}
    1722             :   auto_delete_vec (size_t s) : auto_vec <T *> (s) {}
    1723             : 
    1724             :   ~auto_delete_vec ();
    1725             : 
    1726             : private:
    1727             :   DISABLE_COPY_AND_ASSIGN(auto_delete_vec);
    1728             : };
    1729             : 
    1730             : /* Conditionally allocate heap memory for VEC and its internal vector.  */
    1731             : 
    1732             : template<typename T>
    1733             : inline void
    1734             : vec_check_alloc (vec<T, va_heap> *&vec, unsigned nelems CXX_MEM_STAT_INFO)
    1735             : {
    1736             :   if (!vec)
    1737             :     vec_alloc (vec, nelems PASS_MEM_STAT);
    1738             : }
    1739             : 
    1740             : 
    1741             : /* Free the heap memory allocated by vector V and set it to NULL.  */
    1742             : 
    1743             : template<typename T>
    1744             : inline void
    1745      204166 : vec_free (vec<T> *&v)
    1746             : {
    1747      204166 :   if (v == NULL)
    1748             :     return;
    1749             : 
    1750      107689 :   v->release ();
    1751      107689 :   delete v;
    1752      107689 :   v = NULL;
    1753             : }
    1754             : 
    1755             : 
    1756             : /* Return iteration condition and update PTR to point to the IX'th
    1757             :    element of this vector.  Use this to iterate over the elements of a
    1758             :    vector as follows,
    1759             : 
    1760             :      for (ix = 0; v.iterate (ix, &ptr); ix++)
    1761             :        continue;  */
    1762             : 
    1763             : template<typename T>
    1764             : inline bool
    1765   772135388 : vec<T, va_heap, vl_ptr>::iterate (unsigned ix, T *ptr) const
    1766             : {
    1767   772133738 :   if (m_vec)
    1768  1030035023 :     return m_vec->iterate (ix, ptr);
    1769             :   else
    1770             :     {
    1771           0 :       *ptr = 0;
    1772           0 :       return false;
    1773             :     }
    1774             : }
    1775             : 
    1776             : 
    1777             : /* Return iteration condition and update *PTR to point to the
    1778             :    IX'th element of this vector.  Use this to iterate over the
    1779             :    elements of a vector as follows,
    1780             : 
    1781             :      for (ix = 0; v->iterate (ix, &ptr); ix++)
    1782             :        continue;
    1783             : 
    1784             :    This variant is for vectors of objects.  */
    1785             : 
    1786             : template<typename T>
    1787             : inline bool
    1788        7021 : vec<T, va_heap, vl_ptr>::iterate (unsigned ix, T **ptr) const
    1789             : {
    1790        7021 :   if (m_vec)
    1791        7021 :     return m_vec->iterate (ix, ptr);
    1792             :   else
    1793             :     {
    1794             :       *ptr = 0;
    1795             :       return false;
    1796             :     }
    1797             : }
    1798             : 
    1799             : 
    1800             : /* Convenience macro for forward iteration.  */
    1801             : #define FOR_EACH_VEC_ELT(V, I, P)                       \
    1802             :   for (I = 0; (V).iterate ((I), &(P)); ++(I))
    1803             : 
    1804             : #define FOR_EACH_VEC_SAFE_ELT(V, I, P)                  \
    1805             :   for (I = 0; vec_safe_iterate ((V), (I), &(P)); ++(I))
    1806             : 
    1807             : /* Likewise, but start from FROM rather than 0.  */
    1808             : #define FOR_EACH_VEC_ELT_FROM(V, I, P, FROM)            \
    1809             :   for (I = (FROM); (V).iterate ((I), &(P)); ++(I))
    1810             : 
    1811             : /* Convenience macro for reverse iteration.  */
    1812             : #define FOR_EACH_VEC_ELT_REVERSE(V, I, P)               \
    1813             :   for (I = (V).length () - 1;                           \
    1814             :        (V).iterate ((I), &(P));                             \
    1815             :        (I)--)
    1816             : 
    1817             : #define FOR_EACH_VEC_SAFE_ELT_REVERSE(V, I, P)          \
    1818             :   for (I = vec_safe_length (V) - 1;                     \
    1819             :        vec_safe_iterate ((V), (I), &(P));   \
    1820             :        (I)--)
    1821             : 
    1822             : /* auto_string_vec's dtor, freeing all contained strings, automatically
    1823             :    chaining up to ~auto_vec <char *>, which frees the internal buffer.  */
    1824             : 
    1825             : inline
    1826             : auto_string_vec::~auto_string_vec ()
    1827             : {
    1828             :   int i;
    1829             :   char *str;
    1830             :   FOR_EACH_VEC_ELT (*this, i, str)
    1831             :     free (str);
    1832             : }
    1833             : 
    1834             : /* auto_delete_vec's dtor, deleting all contained items, automatically
    1835             :    chaining up to ~auto_vec <T*>, which frees the internal buffer.  */
    1836             : 
    1837             : template <typename T>
    1838             : inline
    1839           0 : auto_delete_vec<T>::~auto_delete_vec ()
    1840             : {
    1841             :   int i;
    1842             :   T *item;
    1843           0 :   FOR_EACH_VEC_ELT (*this, i, item)
    1844           0 :     delete item;
    1845           0 : }
    1846             : 
    1847             : 
    1848             : /* Return a copy of this vector.  */
    1849             : 
    1850             : template<typename T>
    1851             : inline vec<T, va_heap, vl_ptr>
    1852        1410 : vec<T, va_heap, vl_ptr>::copy (ALONE_MEM_STAT_DECL) const
    1853             : {
    1854        1410 :   vec<T, va_heap, vl_ptr> new_vec{ };
    1855        1410 :   if (length ())
    1856        1410 :     new_vec.m_vec = m_vec->copy (ALONE_PASS_MEM_STAT);
    1857        1410 :   return new_vec;
    1858             : }
    1859             : 
    1860             : 
    1861             : /* Ensure that the vector has at least RESERVE slots available (if
    1862             :    EXACT is false), or exactly RESERVE slots available (if EXACT is
    1863             :    true).
    1864             : 
    1865             :    This may create additional headroom if EXACT is false.
    1866             : 
    1867             :    Note that this can cause the embedded vector to be reallocated.
    1868             :    Returns true iff reallocation actually occurred.  */
    1869             : 
    1870             : template<typename T>
    1871             : inline bool
    1872 14285562065 : vec<T, va_heap, vl_ptr>::reserve (unsigned nelems, bool exact MEM_STAT_DECL)
    1873             : {
    1874 28571124130 :   if (space (nelems))
    1875             :     return false;
    1876             : 
    1877             :   /* For now play a game with va_heap::reserve to hide our auto storage if any,
    1878             :      this is necessary because it doesn't have enough information to know the
    1879             :      embedded vector is in auto storage, and so should not be freed.  */
    1880    90978545 :   vec<T, va_heap, vl_embed> *oldvec = m_vec;
    1881    90978545 :   unsigned int oldsize = 0;
    1882    90978545 :   bool handle_auto_vec = m_vec && using_auto_storage ();
    1883             :   if (handle_auto_vec)
    1884             :     {
    1885      210749 :       m_vec = NULL;
    1886      210749 :       oldsize = oldvec->length ();
    1887      210749 :       nelems += oldsize;
    1888             :     }
    1889             : 
    1890    90978545 :   va_heap::reserve (m_vec, nelems, exact PASS_MEM_STAT);
    1891    90978545 :   if (handle_auto_vec)
    1892             :     {
    1893      210749 :       vec_copy_construct (m_vec->address (), oldvec->address (), oldsize);
    1894      210749 :       m_vec->m_vecpfx.m_num = oldsize;
    1895             :     }
    1896             : 
    1897             :   return true;
    1898             : }
    1899             : 
    1900             : 
    1901             : /* Ensure that this vector has exactly NELEMS slots available.  This
    1902             :    will not create additional headroom.  Note this can cause the
    1903             :    embedded vector to be reallocated.  Returns true iff reallocation
    1904             :    actually occurred.  */
    1905             : 
    1906             : template<typename T>
    1907             : inline bool
    1908    56713586 : vec<T, va_heap, vl_ptr>::reserve_exact (unsigned nelems MEM_STAT_DECL)
    1909             : {
    1910    56073198 :   return reserve (nelems, true PASS_MEM_STAT);
    1911             : }
    1912             : 
    1913             : 
    1914             : /* Create the internal vector and reserve NELEMS for it.  This is
    1915             :    exactly like vec::reserve, but the internal vector is
    1916             :    unconditionally allocated from scratch.  The old one, if it
    1917             :    existed, is lost.  */
    1918             : 
    1919             : template<typename T>
    1920             : inline void
    1921    36179629 : vec<T, va_heap, vl_ptr>::create (unsigned nelems MEM_STAT_DECL)
    1922             : {
    1923    77152119 :   m_vec = NULL;
    1924     1912150 :   if (nelems > 0)
    1925    56088857 :     reserve_exact (nelems PASS_MEM_STAT);
    1926     1912150 : }
    1927             : 
    1928             : 
    1929             : /* Free the memory occupied by the embedded vector.  */
    1930             : 
    1931             : template<typename T>
    1932             : inline void
    1933  1898922986 : vec<T, va_heap, vl_ptr>::release (void)
    1934             : {
    1935  1898922986 :   if (!m_vec)
    1936             :     return;
    1937             : 
    1938  1451717484 :   if (using_auto_storage ())
    1939             :     {
    1940  1382094226 :       m_vec->m_vecpfx.m_num = 0;
    1941  1382094226 :       return;
    1942             :     }
    1943             : 
    1944    69623258 :   va_heap::release (m_vec);
    1945             : }
    1946             : 
    1947             : /* Copy the elements from SRC to the end of this vector as if by memcpy.
    1948             :    SRC and this vector must be allocated with the same memory
    1949             :    allocation mechanism. This vector is assumed to have sufficient
    1950             :    headroom available.  */
    1951             : 
    1952             : template<typename T>
    1953             : inline void
    1954             : vec<T, va_heap, vl_ptr>::splice (const vec<T, va_heap, vl_ptr> &src)
    1955             : {
    1956             :   if (src.length ())
    1957             :     m_vec->splice (*(src.m_vec));
    1958             : }
    1959             : 
    1960             : 
    1961             : /* Copy the elements in SRC to the end of this vector as if by memcpy.
    1962             :    SRC and this vector must be allocated with the same mechanism.
    1963             :    If there is not enough headroom in this vector, it will be reallocated
    1964             :    as needed.  */
    1965             : 
    1966             : template<typename T>
    1967             : inline void
    1968             : vec<T, va_heap, vl_ptr>::safe_splice (const vec<T, va_heap, vl_ptr> &src
    1969             :                                       MEM_STAT_DECL)
    1970             : {
    1971             :   if (src.length ())
    1972             :     {
    1973             :       reserve_exact (src.length ());
    1974             :       splice (src);
    1975             :     }
    1976             : }
    1977             : 
    1978             : 
    1979             : /* Push OBJ (a new element) onto the end of the vector.  There must be
    1980             :    sufficient space in the vector.  Return a pointer to the slot
    1981             :    where OBJ was inserted.  */
    1982             : 
    1983             : template<typename T>
    1984             : inline T *
    1985 14226808876 : vec<T, va_heap, vl_ptr>::quick_push (const T &obj)
    1986             : {
    1987  4499379334 :   return m_vec->quick_push (obj);
    1988             : }
    1989             : 
    1990             : 
    1991             : /* Push a new element OBJ onto the end of this vector.  Reallocates
    1992             :    the embedded vector, if needed.  Return a pointer to the slot where
    1993             :    OBJ was inserted.  */
    1994             : 
    1995             : template<typename T>
    1996             : inline T *
    1997 14216231724 : vec<T, va_heap, vl_ptr>::safe_push (const T &obj MEM_STAT_DECL)
    1998             : {
    1999 14216231724 :   reserve (1, false PASS_MEM_STAT);
    2000 14216231724 :   return quick_push (obj);
    2001             : }
    2002             : 
    2003             : 
    2004             : /* Pop and return the last element off the end of the vector.  */
    2005             : 
    2006             : template<typename T>
    2007             : inline T &
    2008 13552731626 : vec<T, va_heap, vl_ptr>::pop (void)
    2009             : {
    2010 13552731626 :   return m_vec->pop ();
    2011             : }
    2012             : 
    2013             : 
    2014             : /* Set the length of the vector to LEN.  The new length must be less
    2015             :    than or equal to the current length.  This is an O(1) operation.  */
    2016             : 
    2017             : template<typename T>
    2018             : inline void
    2019   107092558 : vec<T, va_heap, vl_ptr>::truncate (unsigned size)
    2020             : {
    2021   107092558 :   if (m_vec)
    2022   107070698 :     m_vec->truncate (size);
    2023             :   else
    2024       21860 :     gcc_checking_assert (size == 0);
    2025   107092558 : }
    2026             : 
    2027             : 
    2028             : /* Grow the vector to a specific length.  LEN must be as long or
    2029             :    longer than the current length.  The new elements are
    2030             :    uninitialized.  Reallocate the internal vector, if needed.  */
    2031             : 
    2032             : template<typename T>
    2033             : inline void
    2034    12613809 : vec<T, va_heap, vl_ptr>::safe_grow (unsigned len, bool exact MEM_STAT_DECL)
    2035             : {
    2036    20700668 :   unsigned oldlen = length ();
    2037     8086859 :   gcc_checking_assert (oldlen <= len);
    2038    12613809 :   reserve (len - oldlen, exact PASS_MEM_STAT);
    2039    12613809 :   if (m_vec)
    2040    12613809 :     m_vec->quick_grow (len);
    2041             :   else
    2042           0 :     gcc_checking_assert (len == 0);
    2043    12613809 : }
    2044             : 
    2045             : 
    2046             : /* Grow the embedded vector to a specific length.  LEN must be as
    2047             :    long or longer than the current length.  The new elements are
    2048             :    initialized to zero.  Reallocate the internal vector, if needed.  */
    2049             : 
    2050             : template<typename T>
    2051             : inline void
    2052     6894120 : vec<T, va_heap, vl_ptr>::safe_grow_cleared (unsigned len, bool exact
    2053             :                                             MEM_STAT_DECL)
    2054             : {
    2055     6894120 :   unsigned oldlen = length ();
    2056     6894120 :   size_t growby = len - oldlen;
    2057     6894120 :   safe_grow (len, exact PASS_MEM_STAT);
    2058     6894120 :   if (growby != 0)
    2059    13788200 :     vec_default_construct (address () + oldlen, growby);
    2060     6894120 : }
    2061             : 
    2062             : 
    2063             : /* Same as vec::safe_grow but without reallocation of the internal vector.
    2064             :    If the vector cannot be extended, a runtime assertion will be triggered.  */
    2065             : 
    2066             : template<typename T>
    2067             : inline void
    2068             : vec<T, va_heap, vl_ptr>::quick_grow (unsigned len)
    2069             : {
    2070             :   gcc_checking_assert (m_vec);
    2071             :   m_vec->quick_grow (len);
    2072             : }
    2073             : 
    2074             : 
    2075             : /* Same as vec::quick_grow_cleared but without reallocation of the
    2076             :    internal vector. If the vector cannot be extended, a runtime
    2077             :    assertion will be triggered.  */
    2078             : 
    2079             : template<typename T>
    2080             : inline void
    2081      585679 : vec<T, va_heap, vl_ptr>::quick_grow_cleared (unsigned len)
    2082             : {
    2083      585679 :   gcc_checking_assert (m_vec);
    2084      585679 :   m_vec->quick_grow_cleared (len);
    2085      585679 : }
    2086             : 
    2087             : 
    2088             : /* Insert an element, OBJ, at the IXth position of this vector.  There
    2089             :    must be sufficient space.  */
    2090             : 
    2091             : template<typename T>
    2092             : inline void
    2093             : vec<T, va_heap, vl_ptr>::quick_insert (unsigned ix, const T &obj)
    2094             : {
    2095             :   m_vec->quick_insert (ix, obj);
    2096             : }
    2097             : 
    2098             : 
    2099             : /* Insert an element, OBJ, at the IXth position of the vector.
    2100             :    Reallocate the embedded vector, if necessary.  */
    2101             : 
    2102             : template<typename T>
    2103             : inline void
    2104             : vec<T, va_heap, vl_ptr>::safe_insert (unsigned ix, const T &obj MEM_STAT_DECL)
    2105             : {
    2106             :   reserve (1, false PASS_MEM_STAT);
    2107             :   quick_insert (ix, obj);
    2108             : }
    2109             : 
    2110             : 
    2111             : /* Remove an element from the IXth position of this vector.  Ordering of
    2112             :    remaining elements is preserved.  This is an O(N) operation due to
    2113             :    a memmove.  */
    2114             : 
    2115             : template<typename T>
    2116             : inline void
    2117             : vec<T, va_heap, vl_ptr>::ordered_remove (unsigned ix)
    2118             : {
    2119             :   m_vec->ordered_remove (ix);
    2120             : }
    2121             : 
    2122             : 
    2123             : /* Remove an element from the IXth position of this vector.  Ordering
    2124             :    of remaining elements is destroyed.  This is an O(1) operation.  */
    2125             : 
    2126             : template<typename T>
    2127             : inline void
    2128          54 : vec<T, va_heap, vl_ptr>::unordered_remove (unsigned ix)
    2129             : {
    2130          54 :   m_vec->unordered_remove (ix);
    2131          54 : }
    2132             : 
    2133             : 
    2134             : /* Remove LEN elements starting at the IXth.  Ordering is retained.
    2135             :    This is an O(N) operation due to memmove.  */
    2136             : 
    2137             : template<typename T>
    2138             : inline void
    2139             : vec<T, va_heap, vl_ptr>::block_remove (unsigned ix, unsigned len)
    2140             : {
    2141             :   m_vec->block_remove (ix, len);
    2142             : }
    2143             : 
    2144             : 
    2145             : /* Sort the contents of this vector with qsort.  CMP is the comparison
    2146             :    function to pass to qsort.  */
    2147             : 
    2148             : template<typename T>
    2149             : inline void
    2150   292791194 : vec<T, va_heap, vl_ptr>::qsort (int (*cmp) (const void *, const void *))
    2151             : {
    2152   292791194 :   if (m_vec)
    2153      318002 :     m_vec->qsort (cmp);
    2154             : }
    2155             : 
    2156             : /* Sort the contents of this vector with qsort.  CMP is the comparison
    2157             :    function to pass to qsort.  */
    2158             : 
    2159             : template<typename T>
    2160             : inline void
    2161             : vec<T, va_heap, vl_ptr>::sort (int (*cmp) (const void *, const void *,
    2162             :                                            void *), void *data)
    2163             : {
    2164             :   if (m_vec)
    2165             :     m_vec->sort (cmp, data);
    2166             : }
    2167             : 
    2168             : /* Sort the contents of this vector with gcc_stablesort_r.  CMP is the
    2169             :    comparison function to pass to qsort.  */
    2170             : 
    2171             : template<typename T>
    2172             : inline void
    2173             : vec<T, va_heap, vl_ptr>::stablesort (int (*cmp) (const void *, const void *,
    2174             :                                                  void *), void *data)
    2175             : {
    2176             :   if (m_vec)
    2177             :     m_vec->stablesort (cmp, data);
    2178             : }
    2179             : 
    2180             : /* Search the contents of the sorted vector with a binary search.
    2181             :    CMP is the comparison function to pass to bsearch.  */
    2182             : 
    2183             : template<typename T>
    2184             : inline T *
    2185             : vec<T, va_heap, vl_ptr>::bsearch (const void *key,
    2186             :                                   int (*cmp) (const void *, const void *))
    2187             : {
    2188             :   if (m_vec)
    2189             :     return m_vec->bsearch (key, cmp);
    2190             :   return NULL;
    2191             : }
    2192             : 
    2193             : /* Search the contents of the sorted vector with a binary search.
    2194             :    CMP is the comparison function to pass to bsearch.  */
    2195             : 
    2196             : template<typename T>
    2197             : inline T *
    2198             : vec<T, va_heap, vl_ptr>::bsearch (const void *key,
    2199             :                                   int (*cmp) (const void *, const void *,
    2200             :                                               void *), void *data)
    2201             : {
    2202             :   if (m_vec)
    2203             :     return m_vec->bsearch (key, cmp, data);
    2204             :   return NULL;
    2205             : }
    2206             : 
    2207             : 
    2208             : /* Find and return the first position in which OBJ could be inserted
    2209             :    without changing the ordering of this vector.  LESSTHAN is a
    2210             :    function that returns true if the first argument is strictly less
    2211             :    than the second.  */
    2212             : 
    2213             : template<typename T>
    2214             : inline unsigned
    2215             : vec<T, va_heap, vl_ptr>::lower_bound (T obj,
    2216             :                                       bool (*lessthan)(const T &, const T &))
    2217             :     const
    2218             : {
    2219             :   return m_vec ? m_vec->lower_bound (obj, lessthan) : 0;
    2220             : }
    2221             : 
    2222             : /* Return true if SEARCH is an element of V.  Note that this is O(N) in the
    2223             :    size of the vector and so should be used with care.  */
    2224             : 
    2225             : template<typename T>
    2226             : inline bool
    2227             : vec<T, va_heap, vl_ptr>::contains (const T &search) const
    2228             : {
    2229             :   return m_vec ? m_vec->contains (search) : false;
    2230             : }
    2231             : 
    2232             : /* Reverse content of the vector.  */
    2233             : 
    2234             : template<typename T>
    2235             : inline void
    2236             : vec<T, va_heap, vl_ptr>::reverse (void)
    2237             : {
    2238             :   unsigned l = length ();
    2239             :   T *ptr = address ();
    2240             : 
    2241             :   for (unsigned i = 0; i < l / 2; i++)
    2242             :     std::swap (ptr[i], ptr[l - i - 1]);
    2243             : }
    2244             : 
    2245             : template<typename T>
    2246             : inline bool
    2247  1469304577 : vec<T, va_heap, vl_ptr>::using_auto_storage () const
    2248             : {
    2249  1469304577 :   return m_vec ? m_vec->m_vecpfx.m_using_auto_storage : false;
    2250             : }
    2251             : 
    2252             : /* Release VEC and call release of all element vectors.  */
    2253             : 
    2254             : template<typename T>
    2255             : inline void
    2256             : release_vec_vec (vec<vec<T> > &vec)
    2257             : {
    2258             :   for (unsigned i = 0; i < vec.length (); i++)
    2259             :     vec[i].release ();
    2260             : 
    2261             :   vec.release ();
    2262             : }
    2263             : 
    2264             : // Provide a subset of the std::span functionality.  (We can't use std::span
    2265             : // itself because it's a C++20 feature.)
    2266             : //
    2267             : // In addition, provide an invalid value that is distinct from all valid
    2268             : // sequences (including the empty sequence).  This can be used to return
    2269             : // failure without having to use std::optional.
    2270             : //
    2271             : // There is no operator bool because it would be ambiguous whether it is
    2272             : // testing for a valid value or an empty sequence.
    2273             : template<typename T>
    2274             : class array_slice
    2275             : {
    2276             :   template<typename OtherT> friend class array_slice;
    2277             : 
    2278             : public:
    2279             :   using value_type = T;
    2280             :   using iterator = T *;
    2281             :   using const_iterator = const T *;
    2282             : 
    2283             :   array_slice () : m_base (nullptr), m_size (0) {}
    2284             : 
    2285             :   template<typename OtherT>
    2286             :   array_slice (array_slice<OtherT> other)
    2287             :     : m_base (other.m_base), m_size (other.m_size) {}
    2288             : 
    2289             :   array_slice (iterator base, unsigned int size)
    2290             :     : m_base (base), m_size (size) {}
    2291             : 
    2292             :   template<size_t N>
    2293             :   array_slice (T (&array)[N]) : m_base (array), m_size (N) {}
    2294             : 
    2295             :   template<typename OtherT>
    2296             :   array_slice (const vec<OtherT> &v)
    2297             :     : m_base (v.address ()), m_size (v.length ()) {}
    2298             : 
    2299             :   template<typename OtherT>
    2300             :   array_slice (vec<OtherT> &v)
    2301             :     : m_base (v.address ()), m_size (v.length ()) {}
    2302             : 
    2303             :   template<typename OtherT, typename A>
    2304             :   array_slice (const vec<OtherT, A, vl_embed> *v)
    2305             :     : m_base (v ? v->address () : nullptr), m_size (v ? v->length () : 0) {}
    2306             : 
    2307             :   template<typename OtherT, typename A>
    2308             :   array_slice (vec<OtherT, A, vl_embed> *v)
    2309             :     : m_base (v ? v->address () : nullptr), m_size (v ? v->length () : 0) {}
    2310             : 
    2311           0 :   iterator begin () { return m_base; }
    2312           0 :   iterator end () { return m_base + m_size; }
    2313             : 
    2314             :   const_iterator begin () const { return m_base; }
    2315             :   const_iterator end () const { return m_base + m_size; }
    2316             : 
    2317             :   value_type &front ();
    2318             :   value_type &back ();
    2319             :   value_type &operator[] (unsigned int i);
    2320             : 
    2321             :   const value_type &front () const;
    2322             :   const value_type &back () const;
    2323             :   const value_type &operator[] (unsigned int i) const;
    2324             : 
    2325             :   size_t size () const { return m_size; }
    2326             :   size_t size_bytes () const { return m_size * sizeof (T); }
    2327             :   bool empty () const { return m_size == 0; }
    2328             : 
    2329             :   // An invalid array_slice that represents a failed operation.  This is
    2330             :   // distinct from an empty slice, which is a valid result in some contexts.
    2331             :   static array_slice invalid () { return { nullptr, ~0U }; }
    2332             : 
    2333             :   // True if the array is valid, false if it is an array like INVALID.
    2334             :   bool is_valid () const { return m_base || m_size == 0; }
    2335             : 
    2336             : private:
    2337             :   iterator m_base;
    2338             :   unsigned int m_size;
    2339             : };
    2340             : 
    2341             : template<typename T>
    2342             : inline typename array_slice<T>::value_type &
    2343             : array_slice<T>::front ()
    2344             : {
    2345             :   gcc_checking_assert (m_size);
    2346             :   return m_base[0];
    2347             : }
    2348             : 
    2349             : template<typename T>
    2350             : inline const typename array_slice<T>::value_type &
    2351             : array_slice<T>::front () const
    2352             : {
    2353             :   gcc_checking_assert (m_size);
    2354             :   return m_base[0];
    2355             : }
    2356             : 
    2357             : template<typename T>
    2358             : inline typename array_slice<T>::value_type &
    2359             : array_slice<T>::back ()
    2360             : {
    2361             :   gcc_checking_assert (m_size);
    2362             :   return m_base[m_size - 1];
    2363             : }
    2364             : 
    2365             : template<typename T>
    2366             : inline const typename array_slice<T>::value_type &
    2367             : array_slice<T>::back () const
    2368             : {
    2369             :   gcc_checking_assert (m_size);
    2370             :   return m_base[m_size - 1];
    2371             : }
    2372             : 
    2373             : template<typename T>
    2374             : inline typename array_slice<T>::value_type &
    2375             : array_slice<T>::operator[] (unsigned int i)
    2376             : {
    2377             :   gcc_checking_assert (i < m_size);
    2378             :   return m_base[i];
    2379             : }
    2380             : 
    2381             : template<typename T>
    2382             : inline const typename array_slice<T>::value_type &
    2383             : array_slice<T>::operator[] (unsigned int i) const
    2384             : {
    2385             :   gcc_checking_assert (i < m_size);
    2386             :   return m_base[i];
    2387             : }
    2388             : 
    2389             : template<typename T>
    2390             : array_slice<T>
    2391             : make_array_slice (T *base, unsigned int size)
    2392             : {
    2393             :   return array_slice<T> (base, size);
    2394             : }
    2395             : 
    2396             : #if (GCC_VERSION >= 3000)
    2397             : # pragma GCC poison m_vec m_vecpfx m_vecdata
    2398             : #endif
    2399             : 
    2400             : #endif // GCC_VEC_H

Generated by: LCOV version 1.16