OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / vec.h
index 8cb9c58..d477958 100644 (file)
--- a/gcc/vec.h
+++ b/gcc/vec.h
@@ -22,6 +22,8 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_VEC_H
 #define GCC_VEC_H
 
+#include "statistics.h"                /* For MEM_STAT_DECL.  */
+
 /* The macros here implement a set of templated vector types and
    associated interfaces.  These templates are implemented with
    macros, as we're not in C++ land.  The interface functions are
@@ -188,6 +190,23 @@ along with GCC; see the file COPYING3.  If not see
 
 #define VEC_iterate(T,V,I,P)   (VEC_OP(T,base,iterate)(VEC_BASE(V),I,&(P)))
 
+/* Convenience macro for forward iteration.  */
+
+#define FOR_EACH_VEC_ELT(T, V, I, P)           \
+  for (I = 0; VEC_iterate (T, (V), (I), (P)); ++(I))
+
+/* Likewise, but start from FROM rather than 0.  */
+
+#define FOR_EACH_VEC_ELT_FROM(T, V, I, P, FROM)                \
+  for (I = (FROM); VEC_iterate (T, (V), (I), (P)); ++(I))
+
+/* Convenience macro for reverse iteration.  */
+
+#define FOR_EACH_VEC_ELT_REVERSE(T,V,I,P) \
+  for (I = VEC_length (T, (V)) - 1;           \
+       VEC_iterate (T, (V), (I), (P));   \
+       (I)--)
+
 /* Allocate new vector.
    VEC(T,A) *VEC_T_A_alloc(int reserve);
 
@@ -257,6 +276,32 @@ along with GCC; see the file COPYING3.  If not see
 #define VEC_reserve_exact(T,A,V,R)     \
        (VEC_OP(T,A,reserve_exact)(&(V),R VEC_CHECK_INFO MEM_STAT_INFO))
 
+/* Copy elements with no reallocation
+   void VEC_T_splice (VEC(T) *dst, VEC(T) *src); // Integer
+   void VEC_T_splice (VEC(T) *dst, VEC(T) *src); // Pointer
+   void VEC_T_splice (VEC(T) *dst, VEC(T) *src); // Object
+
+   Copy the elements in SRC to the end of DST as if by memcpy.  DST and
+   SRC need not be allocated with the same mechanism, although they most
+   often will be.  DST is assumed to have sufficient headroom
+   available.  */
+
+#define VEC_splice(T,DST,SRC)                  \
+  (VEC_OP(T,base,splice)(VEC_BASE(DST), VEC_BASE(SRC) VEC_CHECK_INFO))
+
+/* Copy elements with reallocation
+   void VEC_T_safe_splice (VEC(T,A) *&dst, VEC(T) *src); // Integer
+   void VEC_T_safe_splice (VEC(T,A) *&dst, VEC(T) *src); // Pointer
+   void VEC_T_safe_splice (VEC(T,A) *&dst, VEC(T) *src); // Object
+
+   Copy the elements in SRC to the end of DST as if by memcpy.  DST and
+   SRC need not be allocated with the same mechanism, although they most
+   often will be.  DST need not have sufficient headroom and will be
+   reallocated if needed.  */
+
+#define VEC_safe_splice(T,A,DST,SRC)                                   \
+  (VEC_OP(T,A,safe_splice)(&(DST), VEC_BASE(SRC) VEC_CHECK_INFO MEM_STAT_INFO))
+  
 /* Push object with no reallocation
    T *VEC_T_quick_push (VEC(T) *v, T obj); // Integer
    T *VEC_T_quick_push (VEC(T) *v, T obj); // Pointer
@@ -389,7 +434,7 @@ along with GCC; see the file COPYING3.  If not see
    void VEC_T_block_remove (VEC(T) *v, unsigned ix, unsigned len);
 
    Remove LEN elements starting at the IXth.  Ordering is retained.
-   This is an O(1) operation.  */
+   This is an O(N) operation due to memmove.  */
 
 #define VEC_block_remove(T,V,I,L)      \
        (VEC_OP(T,base,block_remove)(VEC_BASE(V),I,L VEC_CHECK_INFO))
@@ -402,6 +447,12 @@ along with GCC; see the file COPYING3.  If not see
 
 #define VEC_address(T,V)               (VEC_OP(T,base,address)(VEC_BASE(V)))
 
+/* Conveniently sort the contents of the vector with qsort.
+   void VEC_qsort (VEC(T) *v, int (*cmp_func)(const void *, const void *))  */
+
+#define VEC_qsort(T,V,CMP) qsort(VEC_address (T,V), VEC_length(T,V),   \
+                                sizeof (T), CMP)
+
 /* Find the first index in the vector not less than the object.
    unsigned VEC_T_lower_bound (VEC(T) *v, const T val,
                                bool (*lessthan) (const T, const T)); // Integer
@@ -434,7 +485,8 @@ extern void dump_vec_loc_statistics (void);
 #ifdef GATHER_STATISTICS
 void vec_heap_free (void *);
 #else
-#define vec_heap_free(V) free (V)
+/* Avoid problems with frontends that #define free(x).  */
+#define vec_heap_free(V) (free) (V)
 #endif
 
 #if ENABLE_CHECKING
@@ -459,6 +511,12 @@ extern void vec_assert_fail (const char *, const char * VEC_CHECK_DECL)
    VEC, DEF_VEC_*, and DEF_VEC_ALLOC_* macros.  If you change the
    expansions of these macros you may need to change gengtype too.  */
 
+typedef struct GTY(()) vec_prefix
+{
+  unsigned num;
+  unsigned alloc;
+} vec_prefix;
+
 #define VEC(T,A) VEC_##T##_##A
 #define VEC_OP(T,A,OP) VEC_##T##_##A##_##OP
 
@@ -466,17 +524,15 @@ extern void vec_assert_fail (const char *, const char * VEC_CHECK_DECL)
 #define VEC_T(T,B)                                                       \
 typedef struct VEC(T,B)                                                  \
 {                                                                        \
-  unsigned num;                                                                  \
-  unsigned alloc;                                                        \
+  struct vec_prefix prefix;                                              \
   T vec[1];                                                              \
 } VEC(T,B)
 
 #define VEC_T_GTY(T,B)                                                   \
 typedef struct GTY(()) VEC(T,B)                                                  \
 {                                                                        \
-  unsigned num;                                                                  \
-  unsigned alloc;                                                        \
-  T GTY ((length ("%h.num"))) vec[1];                                    \
+  struct vec_prefix prefix;                                              \
+  T GTY ((length ("%h.prefix.num"))) vec[1];                             \
 } VEC(T,B)
 
 /* Derived vector type, user visible.  */
@@ -493,7 +549,12 @@ typedef struct VEC(T,A)                                                      \
 } VEC(T,A)
 
 /* Convert to base type.  */
+#if GCC_VERSION >= 4000
+#define VEC_BASE(P) \
+  ((offsetof (__typeof (*P), base) == 0 || (P)) ? &(P)->base : 0)
+#else
 #define VEC_BASE(P)  ((P) ? &(P)->base : 0)
+#endif
 
 /* Vector of integer-like object.  */
 #define DEF_VEC_I(T)                                                     \
@@ -532,21 +593,21 @@ struct vec_swallow_trailing_semi
 #define DEF_VEC_FUNC_P(T)                                                \
 static inline unsigned VEC_OP (T,base,length) (const VEC(T,base) *vec_)   \
 {                                                                        \
-  return vec_ ? vec_->num : 0;                                           \
+  return vec_ ? vec_->prefix.num : 0;                                            \
 }                                                                        \
                                                                          \
 static inline T VEC_OP (T,base,last)                                     \
      (const VEC(T,base) *vec_ VEC_CHECK_DECL)                            \
 {                                                                        \
-  VEC_ASSERT (vec_ && vec_->num, "last", T, base);                       \
+  VEC_ASSERT (vec_ && vec_->prefix.num, "last", T, base);                        \
                                                                          \
-  return vec_->vec[vec_->num - 1];                                       \
+  return vec_->vec[vec_->prefix.num - 1];                                        \
 }                                                                        \
                                                                          \
 static inline T VEC_OP (T,base,index)                                    \
      (const VEC(T,base) *vec_, unsigned ix_ VEC_CHECK_DECL)              \
 {                                                                        \
-  VEC_ASSERT (vec_ && ix_ < vec_->num, "index", T, base);                \
+  VEC_ASSERT (vec_ && ix_ < vec_->prefix.num, "index", T, base);                 \
                                                                          \
   return vec_->vec[ix_];                                                 \
 }                                                                        \
@@ -554,7 +615,7 @@ static inline T VEC_OP (T,base,index)                                         \
 static inline int VEC_OP (T,base,iterate)                                \
      (const VEC(T,base) *vec_, unsigned ix_, T *ptr)                     \
 {                                                                        \
-  if (vec_ && ix_ < vec_->num)                                           \
+  if (vec_ && ix_ < vec_->prefix.num)                                            \
     {                                                                    \
       *ptr = vec_->vec[ix_];                                             \
       return 1;                                                                  \
@@ -575,15 +636,28 @@ static inline size_t VEC_OP (T,base,embedded_size)                          \
 static inline void VEC_OP (T,base,embedded_init)                         \
      (VEC(T,base) *vec_, int alloc_)                                     \
 {                                                                        \
-  vec_->num = 0;                                                         \
-  vec_->alloc = alloc_;                                                          \
+  vec_->prefix.num = 0;                                                          \
+  vec_->prefix.alloc = alloc_;                                                   \
 }                                                                        \
                                                                          \
 static inline int VEC_OP (T,base,space)                                          \
      (VEC(T,base) *vec_, int alloc_ VEC_CHECK_DECL)                      \
 {                                                                        \
   VEC_ASSERT (alloc_ >= 0, "space", T, base);                            \
-  return vec_ ? vec_->alloc - vec_->num >= (unsigned)alloc_ : !alloc_;   \
+  return vec_ ? vec_->prefix.alloc - vec_->prefix.num >= (unsigned)alloc_ : !alloc_;     \
+}                                                                        \
+                                                                         \
+static inline void VEC_OP(T,base,splice)                                 \
+     (VEC(T,base) *dst_, VEC(T,base) *src_ VEC_CHECK_DECL)               \
+{                                                                        \
+  if (src_)                                                              \
+    {                                                                    \
+      unsigned len_ = src_->prefix.num;                                          \
+      VEC_ASSERT (dst_->prefix.num + len_ <= dst_->prefix.alloc, "splice", T, base);     \
+                                                                         \
+      memcpy (&dst_->vec[dst_->prefix.num], &src_->vec[0], len_ * sizeof (T));   \
+      dst_->prefix.num += len_;                                                  \
+    }                                                                    \
 }                                                                        \
                                                                          \
 static inline T *VEC_OP (T,base,quick_push)                              \
@@ -591,8 +665,8 @@ static inline T *VEC_OP (T,base,quick_push)                           \
 {                                                                        \
   T *slot_;                                                              \
                                                                          \
-  VEC_ASSERT (vec_->num < vec_->alloc, "push", T, base);                 \
-  slot_ = &vec_->vec[vec_->num++];                                       \
+  VEC_ASSERT (vec_->prefix.num < vec_->prefix.alloc, "push", T, base);           \
+  slot_ = &vec_->vec[vec_->prefix.num++];                                        \
   *slot_ = obj_;                                                         \
                                                                          \
   return slot_;                                                                  \
@@ -602,8 +676,8 @@ static inline T VEC_OP (T,base,pop) (VEC(T,base) *vec_ VEC_CHECK_DECL)        \
 {                                                                        \
   T obj_;                                                                \
                                                                          \
-  VEC_ASSERT (vec_->num, "pop", T, base);                                \
-  obj_ = vec_->vec[--vec_->num];                                         \
+  VEC_ASSERT (vec_->prefix.num, "pop", T, base);                                 \
+  obj_ = vec_->vec[--vec_->prefix.num];                                          \
                                                                          \
   return obj_;                                                           \
 }                                                                        \
@@ -611,9 +685,9 @@ static inline T VEC_OP (T,base,pop) (VEC(T,base) *vec_ VEC_CHECK_DECL)        \
 static inline void VEC_OP (T,base,truncate)                              \
      (VEC(T,base) *vec_, unsigned size_ VEC_CHECK_DECL)                          \
 {                                                                        \
-  VEC_ASSERT (vec_ ? vec_->num >= size_ : !size_, "truncate", T, base);          \
+  VEC_ASSERT (vec_ ? vec_->prefix.num >= size_ : !size_, "truncate", T, base);   \
   if (vec_)                                                              \
-    vec_->num = size_;                                                   \
+    vec_->prefix.num = size_;                                                    \
 }                                                                        \
                                                                          \
 static inline T VEC_OP (T,base,replace)                                          \
@@ -621,7 +695,7 @@ static inline T VEC_OP (T,base,replace)                                       \
 {                                                                        \
   T old_obj_;                                                            \
                                                                          \
-  VEC_ASSERT (ix_ < vec_->num, "replace", T, base);                      \
+  VEC_ASSERT (ix_ < vec_->prefix.num, "replace", T, base);                       \
   old_obj_ = vec_->vec[ix_];                                             \
   vec_->vec[ix_] = obj_;                                                 \
                                                                          \
@@ -633,10 +707,10 @@ static inline T *VEC_OP (T,base,quick_insert)                               \
 {                                                                        \
   T *slot_;                                                              \
                                                                          \
-  VEC_ASSERT (vec_->num < vec_->alloc, "insert", T, base);               \
-  VEC_ASSERT (ix_ <= vec_->num, "insert", T, base);                      \
+  VEC_ASSERT (vec_->prefix.num < vec_->prefix.alloc, "insert", T, base);                 \
+  VEC_ASSERT (ix_ <= vec_->prefix.num, "insert", T, base);                       \
   slot_ = &vec_->vec[ix_];                                               \
-  memmove (slot_ + 1, slot_, (vec_->num++ - ix_) * sizeof (T));                  \
+  memmove (slot_ + 1, slot_, (vec_->prefix.num++ - ix_) * sizeof (T));           \
   *slot_ = obj_;                                                         \
                                                                          \
   return slot_;                                                                  \
@@ -648,10 +722,10 @@ static inline T VEC_OP (T,base,ordered_remove)                              \
   T *slot_;                                                              \
   T obj_;                                                                \
                                                                          \
-  VEC_ASSERT (ix_ < vec_->num, "remove", T, base);                       \
+  VEC_ASSERT (ix_ < vec_->prefix.num, "remove", T, base);                        \
   slot_ = &vec_->vec[ix_];                                               \
   obj_ = *slot_;                                                         \
-  memmove (slot_, slot_ + 1, (--vec_->num - ix_) * sizeof (T));          \
+  memmove (slot_, slot_ + 1, (--vec_->prefix.num - ix_) * sizeof (T));           \
                                                                          \
   return obj_;                                                           \
 }                                                                        \
@@ -662,10 +736,10 @@ static inline T VEC_OP (T,base,unordered_remove)                    \
   T *slot_;                                                              \
   T obj_;                                                                \
                                                                          \
-  VEC_ASSERT (ix_ < vec_->num, "remove", T, base);                       \
+  VEC_ASSERT (ix_ < vec_->prefix.num, "remove", T, base);                        \
   slot_ = &vec_->vec[ix_];                                               \
   obj_ = *slot_;                                                         \
-  *slot_ = vec_->vec[--vec_->num];                                       \
+  *slot_ = vec_->vec[--vec_->prefix.num];                                        \
                                                                          \
   return obj_;                                                           \
 }                                                                        \
@@ -675,10 +749,10 @@ static inline void VEC_OP (T,base,block_remove)                             \
 {                                                                        \
   T *slot_;                                                              \
                                                                          \
-  VEC_ASSERT (ix_ + len_ <= vec_->num, "block_remove", T, base);         \
+  VEC_ASSERT (ix_ + len_ <= vec_->prefix.num, "block_remove", T, base);          \
   slot_ = &vec_->vec[ix_];                                               \
-  vec_->num -= len_;                                                     \
-  memmove (slot_, slot_ + len_, (vec_->num - ix_) * sizeof (T));         \
+  vec_->prefix.num -= len_;                                                      \
+  memmove (slot_, slot_ + len_, (vec_->prefix.num - ix_) * sizeof (T));          \
 }                                                                        \
                                                                          \
 static inline T *VEC_OP (T,base,address)                                 \
@@ -733,7 +807,7 @@ static inline void VEC_OP (T,A,free)                                          \
                                                                          \
 static inline VEC(T,A) *VEC_OP (T,A,copy) (VEC(T,base) *vec_ MEM_STAT_DECL) \
 {                                                                        \
-  size_t len_ = vec_ ? vec_->num : 0;                                    \
+  size_t len_ = vec_ ? vec_->prefix.num : 0;                                     \
   VEC (T,A) *new_vec_ = NULL;                                            \
                                                                          \
   if (len_)                                                              \
@@ -741,7 +815,7 @@ static inline VEC(T,A) *VEC_OP (T,A,copy) (VEC(T,base) *vec_ MEM_STAT_DECL) \
       new_vec_ = (VEC (T,A) *)(vec_##A##_p_reserve_exact                 \
                               (NULL, len_ PASS_MEM_STAT));               \
                                                                          \
-      new_vec_->base.num = len_;                                         \
+      new_vec_->base.prefix.num = len_;                                          \
       memcpy (new_vec_->base.vec, vec_->vec, sizeof (T) * len_);         \
     }                                                                    \
   return new_vec_;                                                       \
@@ -779,9 +853,9 @@ static inline void VEC_OP (T,A,safe_grow)                             \
              && VEC_OP(T,base,length) VEC_BASE(*vec_) <= (unsigned)size_, \
                                                 "grow", T, A);           \
   VEC_OP (T,A,reserve_exact) (vec_,                                      \
-                             size_ - (int)(*vec_ ? VEC_BASE(*vec_)->num : 0) \
+                             size_ - (int)(*vec_ ? VEC_BASE(*vec_)->prefix.num : 0) \
                              VEC_CHECK_PASS PASS_MEM_STAT);              \
-  VEC_BASE (*vec_)->num = size_;                                         \
+  VEC_BASE (*vec_)->prefix.num = size_;                                          \
 }                                                                        \
                                                                          \
 static inline void VEC_OP (T,A,safe_grow_cleared)                        \
@@ -793,6 +867,19 @@ static inline void VEC_OP (T,A,safe_grow_cleared)                    \
          sizeof (T) * (size_ - oldsize));                                \
 }                                                                        \
                                                                          \
+static inline void VEC_OP(T,A,safe_splice)                               \
+     (VEC(T,A) **dst_, VEC(T,base) *src_ VEC_CHECK_DECL MEM_STAT_DECL)   \
+{                                                                        \
+  if (src_)                                                              \
+    {                                                                    \
+      VEC_OP (T,A,reserve_exact) (dst_, src_->prefix.num                         \
+                                 VEC_CHECK_PASS MEM_STAT_INFO);          \
+                                                                         \
+      VEC_OP (T,base,splice) (VEC_BASE (*dst_), src_                     \
+                             VEC_CHECK_PASS);                            \
+    }                                                                    \
+}                                                                        \
+                                                                         \
 static inline T *VEC_OP (T,A,safe_push)                                          \
      (VEC(T,A) **vec_, T obj_ VEC_CHECK_DECL MEM_STAT_DECL)              \
 {                                                                        \
@@ -825,20 +912,20 @@ struct vec_swallow_trailing_semi
 #define DEF_VEC_FUNC_O(T)                                                \
 static inline unsigned VEC_OP (T,base,length) (const VEC(T,base) *vec_)          \
 {                                                                        \
-  return vec_ ? vec_->num : 0;                                           \
+  return vec_ ? vec_->prefix.num : 0;                                            \
 }                                                                        \
                                                                          \
 static inline T *VEC_OP (T,base,last) (VEC(T,base) *vec_ VEC_CHECK_DECL)  \
 {                                                                        \
-  VEC_ASSERT (vec_ && vec_->num, "last", T, base);                       \
+  VEC_ASSERT (vec_ && vec_->prefix.num, "last", T, base);                        \
                                                                          \
-  return &vec_->vec[vec_->num - 1];                                      \
+  return &vec_->vec[vec_->prefix.num - 1];                                       \
 }                                                                        \
                                                                          \
 static inline T *VEC_OP (T,base,index)                                   \
      (VEC(T,base) *vec_, unsigned ix_ VEC_CHECK_DECL)                    \
 {                                                                        \
-  VEC_ASSERT (vec_ && ix_ < vec_->num, "index", T, base);                \
+  VEC_ASSERT (vec_ && ix_ < vec_->prefix.num, "index", T, base);                 \
                                                                          \
   return &vec_->vec[ix_];                                                \
 }                                                                        \
@@ -846,7 +933,7 @@ static inline T *VEC_OP (T,base,index)                                        \
 static inline int VEC_OP (T,base,iterate)                                \
      (VEC(T,base) *vec_, unsigned ix_, T **ptr)                                  \
 {                                                                        \
-  if (vec_ && ix_ < vec_->num)                                           \
+  if (vec_ && ix_ < vec_->prefix.num)                                            \
     {                                                                    \
       *ptr = &vec_->vec[ix_];                                            \
       return 1;                                                                  \
@@ -867,15 +954,28 @@ static inline size_t VEC_OP (T,base,embedded_size)                          \
 static inline void VEC_OP (T,base,embedded_init)                         \
      (VEC(T,base) *vec_, int alloc_)                                     \
 {                                                                        \
-  vec_->num = 0;                                                         \
-  vec_->alloc = alloc_;                                                          \
+  vec_->prefix.num = 0;                                                          \
+  vec_->prefix.alloc = alloc_;                                                   \
 }                                                                        \
                                                                          \
 static inline int VEC_OP (T,base,space)                                          \
      (VEC(T,base) *vec_, int alloc_ VEC_CHECK_DECL)                      \
 {                                                                        \
   VEC_ASSERT (alloc_ >= 0, "space", T, base);                            \
-  return vec_ ? vec_->alloc - vec_->num >= (unsigned)alloc_ : !alloc_;   \
+  return vec_ ? vec_->prefix.alloc - vec_->prefix.num >= (unsigned)alloc_ : !alloc_;     \
+}                                                                        \
+                                                                         \
+static inline void VEC_OP(T,base,splice)                                 \
+     (VEC(T,base) *dst_, VEC(T,base) *src_ VEC_CHECK_DECL)               \
+{                                                                        \
+  if (src_)                                                              \
+    {                                                                    \
+      unsigned len_ = src_->prefix.num;                                          \
+      VEC_ASSERT (dst_->prefix.num + len_ <= dst_->prefix.alloc, "splice", T, base);     \
+                                                                         \
+      memcpy (&dst_->vec[dst_->prefix.num], &src_->vec[0], len_ * sizeof (T));   \
+      dst_->prefix.num += len_;                                                  \
+    }                                                                    \
 }                                                                        \
                                                                          \
 static inline T *VEC_OP (T,base,quick_push)                              \
@@ -883,8 +983,8 @@ static inline T *VEC_OP (T,base,quick_push)                           \
 {                                                                        \
   T *slot_;                                                              \
                                                                          \
-  VEC_ASSERT (vec_->num < vec_->alloc, "push", T, base);                 \
-  slot_ = &vec_->vec[vec_->num++];                                       \
+  VEC_ASSERT (vec_->prefix.num < vec_->prefix.alloc, "push", T, base);           \
+  slot_ = &vec_->vec[vec_->prefix.num++];                                        \
   if (obj_)                                                              \
     *slot_ = *obj_;                                                      \
                                                                          \
@@ -893,16 +993,16 @@ static inline T *VEC_OP (T,base,quick_push)                                 \
                                                                          \
 static inline void VEC_OP (T,base,pop) (VEC(T,base) *vec_ VEC_CHECK_DECL) \
 {                                                                        \
-  VEC_ASSERT (vec_->num, "pop", T, base);                                \
-  --vec_->num;                                                           \
+  VEC_ASSERT (vec_->prefix.num, "pop", T, base);                                 \
+  --vec_->prefix.num;                                                            \
 }                                                                        \
                                                                          \
 static inline void VEC_OP (T,base,truncate)                              \
      (VEC(T,base) *vec_, unsigned size_ VEC_CHECK_DECL)                          \
 {                                                                        \
-  VEC_ASSERT (vec_ ? vec_->num >= size_ : !size_, "truncate", T, base);          \
+  VEC_ASSERT (vec_ ? vec_->prefix.num >= size_ : !size_, "truncate", T, base);   \
   if (vec_)                                                              \
-    vec_->num = size_;                                                   \
+    vec_->prefix.num = size_;                                                    \
 }                                                                        \
                                                                          \
 static inline T *VEC_OP (T,base,replace)                                 \
@@ -910,7 +1010,7 @@ static inline T *VEC_OP (T,base,replace)                             \
 {                                                                        \
   T *slot_;                                                              \
                                                                          \
-  VEC_ASSERT (ix_ < vec_->num, "replace", T, base);                      \
+  VEC_ASSERT (ix_ < vec_->prefix.num, "replace", T, base);                       \
   slot_ = &vec_->vec[ix_];                                               \
   if (obj_)                                                              \
     *slot_ = *obj_;                                                      \
@@ -923,10 +1023,10 @@ static inline T *VEC_OP (T,base,quick_insert)                              \
 {                                                                        \
   T *slot_;                                                              \
                                                                          \
-  VEC_ASSERT (vec_->num < vec_->alloc, "insert", T, base);               \
-  VEC_ASSERT (ix_ <= vec_->num, "insert", T, base);                      \
+  VEC_ASSERT (vec_->prefix.num < vec_->prefix.alloc, "insert", T, base);                 \
+  VEC_ASSERT (ix_ <= vec_->prefix.num, "insert", T, base);                       \
   slot_ = &vec_->vec[ix_];                                               \
-  memmove (slot_ + 1, slot_, (vec_->num++ - ix_) * sizeof (T));                  \
+  memmove (slot_ + 1, slot_, (vec_->prefix.num++ - ix_) * sizeof (T));           \
   if (obj_)                                                              \
     *slot_ = *obj_;                                                      \
                                                                          \
@@ -938,16 +1038,16 @@ static inline void VEC_OP (T,base,ordered_remove)                          \
 {                                                                        \
   T *slot_;                                                              \
                                                                          \
-  VEC_ASSERT (ix_ < vec_->num, "remove", T, base);                       \
+  VEC_ASSERT (ix_ < vec_->prefix.num, "remove", T, base);                        \
   slot_ = &vec_->vec[ix_];                                               \
-  memmove (slot_, slot_ + 1, (--vec_->num - ix_) * sizeof (T));                  \
+  memmove (slot_, slot_ + 1, (--vec_->prefix.num - ix_) * sizeof (T));           \
 }                                                                        \
                                                                          \
 static inline void VEC_OP (T,base,unordered_remove)                      \
      (VEC(T,base) *vec_, unsigned ix_ VEC_CHECK_DECL)                    \
 {                                                                        \
-  VEC_ASSERT (ix_ < vec_->num, "remove", T, base);                       \
-  vec_->vec[ix_] = vec_->vec[--vec_->num];                               \
+  VEC_ASSERT (ix_ < vec_->prefix.num, "remove", T, base);                        \
+  vec_->vec[ix_] = vec_->vec[--vec_->prefix.num];                                \
 }                                                                        \
                                                                          \
 static inline void VEC_OP (T,base,block_remove)                                  \
@@ -955,10 +1055,10 @@ static inline void VEC_OP (T,base,block_remove)                            \
 {                                                                        \
   T *slot_;                                                              \
                                                                          \
-  VEC_ASSERT (ix_ + len_ <= vec_->num, "block_remove", T, base);         \
+  VEC_ASSERT (ix_ + len_ <= vec_->prefix.num, "block_remove", T, base);          \
   slot_ = &vec_->vec[ix_];                                               \
-  vec_->num -= len_;                                                     \
-  memmove (slot_, slot_ + len_, (vec_->num - ix_) * sizeof (T));         \
+  vec_->prefix.num -= len_;                                                      \
+  memmove (slot_, slot_ + len_, (vec_->prefix.num - ix_) * sizeof (T));          \
 }                                                                        \
                                                                          \
 static inline T *VEC_OP (T,base,address)                                 \
@@ -1006,7 +1106,7 @@ static inline VEC(T,A) *VEC_OP (T,A,alloc)                          \
 #define DEF_VEC_NONALLOC_FUNCS_O(T,A)                                    \
 static inline VEC(T,A) *VEC_OP (T,A,copy) (VEC(T,base) *vec_ MEM_STAT_DECL) \
 {                                                                        \
-  size_t len_ = vec_ ? vec_->num : 0;                                    \
+  size_t len_ = vec_ ? vec_->prefix.num : 0;                                     \
   VEC (T,A) *new_vec_ = NULL;                                            \
                                                                          \
   if (len_)                                                              \
@@ -1016,7 +1116,7 @@ static inline VEC(T,A) *VEC_OP (T,A,copy) (VEC(T,base) *vec_ MEM_STAT_DECL) \
                                offsetof (VEC(T,A),base.vec), sizeof (T)  \
                                PASS_MEM_STAT));                          \
                                                                          \
-      new_vec_->base.num = len_;                                         \
+      new_vec_->base.prefix.num = len_;                                          \
       memcpy (new_vec_->base.vec, vec_->vec, sizeof (T) * len_);         \
     }                                                                    \
   return new_vec_;                                                       \
@@ -1067,9 +1167,9 @@ static inline void VEC_OP (T,A,safe_grow)                           \
              && VEC_OP(T,base,length) VEC_BASE(*vec_) <= (unsigned)size_, \
                                                 "grow", T, A);           \
   VEC_OP (T,A,reserve_exact) (vec_,                                      \
-                             size_ - (int)(*vec_ ? VEC_BASE(*vec_)->num : 0) \
+                             size_ - (int)(*vec_ ? VEC_BASE(*vec_)->prefix.num : 0) \
                              VEC_CHECK_PASS PASS_MEM_STAT);              \
-  VEC_BASE (*vec_)->num = size_;                                         \
+  VEC_BASE (*vec_)->prefix.num = size_;                                          \
 }                                                                        \
                                                                          \
 static inline void VEC_OP (T,A,safe_grow_cleared)                        \
@@ -1081,6 +1181,19 @@ static inline void VEC_OP (T,A,safe_grow_cleared)                          \
          sizeof (T) * (size_ - oldsize));                                \
 }                                                                        \
                                                                          \
+static inline void VEC_OP(T,A,safe_splice)                               \
+     (VEC(T,A) **dst_, VEC(T,base) *src_ VEC_CHECK_DECL MEM_STAT_DECL)   \
+{                                                                        \
+  if (src_)                                                              \
+    {                                                                    \
+      VEC_OP (T,A,reserve_exact) (dst_, src_->prefix.num                         \
+                                 VEC_CHECK_PASS MEM_STAT_INFO);          \
+                                                                         \
+      VEC_OP (T,base,splice) (VEC_BASE (*dst_), src_                     \
+                             VEC_CHECK_PASS);                            \
+    }                                                                    \
+}                                                                        \
+                                                                         \
 static inline T *VEC_OP (T,A,safe_push)                                          \
      (VEC(T,A) **vec_, const T *obj_ VEC_CHECK_DECL MEM_STAT_DECL)       \
 {                                                                        \
@@ -1111,7 +1224,7 @@ static inline VEC(T,A) *VEC_OP (T,A,alloc)                          \
 #define DEF_VEC_NONALLOC_FUNCS_I(T,A)                                    \
 static inline VEC(T,A) *VEC_OP (T,A,copy) (VEC(T,base) *vec_ MEM_STAT_DECL) \
 {                                                                        \
-  size_t len_ = vec_ ? vec_->num : 0;                                    \
+  size_t len_ = vec_ ? vec_->prefix.num : 0;                                     \
   VEC (T,A) *new_vec_ = NULL;                                            \
                                                                          \
   if (len_)                                                              \
@@ -1121,7 +1234,7 @@ static inline VEC(T,A) *VEC_OP (T,A,copy) (VEC(T,base) *vec_ MEM_STAT_DECL) \
                                offsetof (VEC(T,A),base.vec), sizeof (T)  \
                                PASS_MEM_STAT));                          \
                                                                          \
-      new_vec_->base.num = len_;                                         \
+      new_vec_->base.prefix.num = len_;                                          \
       memcpy (new_vec_->base.vec, vec_->vec, sizeof (T) * len_);         \
     }                                                                    \
   return new_vec_;                                                       \
@@ -1171,9 +1284,9 @@ static inline void VEC_OP (T,A,safe_grow)                           \
              && VEC_OP(T,base,length) VEC_BASE(*vec_) <= (unsigned)size_, \
                                                 "grow", T, A);           \
   VEC_OP (T,A,reserve_exact) (vec_,                                      \
-                             size_ - (int)(*vec_ ? VEC_BASE(*vec_)->num : 0) \
+                             size_ - (int)(*vec_ ? VEC_BASE(*vec_)->prefix.num : 0) \
                              VEC_CHECK_PASS PASS_MEM_STAT);              \
-  VEC_BASE (*vec_)->num = size_;                                         \
+  VEC_BASE (*vec_)->prefix.num = size_;                                          \
 }                                                                        \
                                                                          \
 static inline void VEC_OP (T,A,safe_grow_cleared)                        \
@@ -1185,6 +1298,19 @@ static inline void VEC_OP (T,A,safe_grow_cleared)                          \
          sizeof (T) * (size_ - oldsize));                                \
 }                                                                        \
                                                                          \
+static inline void VEC_OP(T,A,safe_splice)                               \
+     (VEC(T,A) **dst_, VEC(T,base) *src_ VEC_CHECK_DECL MEM_STAT_DECL)   \
+{                                                                        \
+  if (src_)                                                              \
+    {                                                                    \
+      VEC_OP (T,A,reserve_exact) (dst_, src_->prefix.num                         \
+                                 VEC_CHECK_PASS MEM_STAT_INFO);          \
+                                                                         \
+      VEC_OP (T,base,splice) (VEC_BASE (*dst_), src_                     \
+                             VEC_CHECK_PASS);                            \
+    }                                                                    \
+}                                                                        \
+                                                                         \
 static inline T *VEC_OP (T,A,safe_push)                                          \
      (VEC(T,A) **vec_, const T obj_ VEC_CHECK_DECL MEM_STAT_DECL)        \
 {                                                                        \