aboutsummaryrefslogtreecommitdiff
path: root/gcc/vec.h
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/vec.h')
-rw-r--r--gcc/vec.h1739
1 files changed, 738 insertions, 1001 deletions
diff --git a/gcc/vec.h b/gcc/vec.h
index cb87112..5fdb859 100644
--- a/gcc/vec.h
+++ b/gcc/vec.h
@@ -1,7 +1,8 @@
/* Vector API for GNU compiler.
- Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010
+ Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010, 2011, 2012
Free Software Foundation, Inc.
Contributed by Nathan Sidwell <nathan@codesourcery.com>
+ Re-implemented in C++ by Diego Novillo <dnovillo@google.com>
This file is part of GCC.
@@ -134,6 +135,153 @@ along with GCC; see the file COPYING3. If not see
*/
+#if ENABLE_CHECKING
+#define VEC_CHECK_INFO ,__FILE__,__LINE__,__FUNCTION__
+#define VEC_CHECK_DECL ,const char *file_,unsigned line_,const char *function_
+#define VEC_CHECK_PASS ,file_,line_,function_
+
+#define VEC_ASSERT(EXPR,OP,T,A) \
+ (void)((EXPR) ? 0 : (VEC_ASSERT_FAIL(OP,VEC(T,A)), 0))
+
+extern void vec_assert_fail (const char *, const char * VEC_CHECK_DECL)
+ ATTRIBUTE_NORETURN;
+#define VEC_ASSERT_FAIL(OP,VEC) vec_assert_fail (OP,#VEC VEC_CHECK_PASS)
+#else
+#define VEC_CHECK_INFO
+#define VEC_CHECK_DECL
+#define VEC_CHECK_PASS
+#define VEC_ASSERT(EXPR,OP,T,A) (void)(EXPR)
+#endif
+
+#define VEC(T,A) vec_t<T>
+
+enum vec_allocation_t { heap, gc, stack };
+
+struct vec_prefix
+{
+ unsigned num;
+ unsigned alloc;
+};
+
+/* Vector type, user visible. */
+template<typename T>
+struct GTY(()) vec_t
+{
+ vec_prefix prefix;
+ T vec[1];
+};
+
+/* Garbage collection support for vec_t. */
+
+template<typename T>
+void
+gt_ggc_mx (vec_t<T> *v)
+{
+ extern void gt_ggc_mx (T&);
+ for (unsigned i = 0; i < v->prefix.num; i++)
+ gt_ggc_mx (v->vec[i]);
+}
+
+
+/* PCH support for vec_t. */
+
+template<typename T>
+void
+gt_pch_nx (vec_t<T> *v)
+{
+ extern void gt_pch_nx (T&);
+ for (unsigned i = 0; i < v->prefix.num; i++)
+ gt_pch_nx (v->vec[i]);
+}
+
+template<typename T>
+void
+gt_pch_nx (vec_t<T *> *v, gt_pointer_operator op, void *cookie)
+{
+ for (unsigned i = 0; i < v->prefix.num; i++)
+ op (&(v->vec[i]), cookie);
+}
+
+template<typename T>
+void
+gt_pch_nx (vec_t<T> *v, gt_pointer_operator op, void *cookie)
+{
+ extern void gt_pch_nx (T *, gt_pointer_operator, void *);
+ for (unsigned i = 0; i < v->prefix.num; i++)
+ gt_pch_nx (&(v->vec[i]), op, cookie);
+}
+
+
+/* FIXME cxx-conversion. Remove these definitions and update all
+ calling sites. */
+/* Vector of integer-like object. */
+#define DEF_VEC_I(T) struct vec_swallow_trailing_semi
+#define DEF_VEC_ALLOC_I(T,A) struct vec_swallow_trailing_semi
+
+/* Vector of pointer to object. */
+#define DEF_VEC_P(T) struct vec_swallow_trailing_semi
+#define DEF_VEC_ALLOC_P(T,A) struct vec_swallow_trailing_semi
+
+/* Vector of object. */
+#define DEF_VEC_O(T) struct vec_swallow_trailing_semi
+#define DEF_VEC_ALLOC_O(T,A) struct vec_swallow_trailing_semi
+
+/* Vectors on the stack. */
+#define DEF_VEC_ALLOC_P_STACK(T) struct vec_swallow_trailing_semi
+#define DEF_VEC_ALLOC_O_STACK(T) struct vec_swallow_trailing_semi
+#define DEF_VEC_ALLOC_I_STACK(T) struct vec_swallow_trailing_semi
+
+/* Vectors of atomic types. Atomic types do not need to have its
+ elements marked for GC and PCH. To avoid unnecessary traversals,
+ we provide template instantiations for the GC/PCH functions that
+ do not traverse the vector.
+
+ FIXME cxx-conversion - Once vec_t users are converted this can
+ be provided in some other way (e.g., adding an additional template
+ parameter to the vec_t class). */
+#define DEF_VEC_A(TYPE) \
+template<typename T> \
+void \
+gt_ggc_mx (vec_t<TYPE> *v ATTRIBUTE_UNUSED) \
+{ \
+} \
+ \
+template<typename T> \
+void \
+gt_pch_nx (vec_t<TYPE> *v ATTRIBUTE_UNUSED) \
+{ \
+} \
+ \
+template<typename T> \
+void \
+gt_pch_nx (vec_t<TYPE> *v ATTRIBUTE_UNUSED, \
+ gt_pointer_operator op ATTRIBUTE_UNUSED, \
+ void *cookie ATTRIBUTE_UNUSED) \
+{ \
+} \
+struct vec_swallow_trailing_semi
+
+#define DEF_VEC_ALLOC_A(T,A) struct vec_swallow_trailing_semi
+
+/* Support functions for stack vectors. */
+extern void *vec_stack_p_reserve_exact_1 (int, void *);
+extern void *vec_stack_o_reserve (void *, int, size_t, size_t MEM_STAT_DECL);
+extern void *vec_stack_o_reserve_exact (void *, int, size_t, size_t
+ MEM_STAT_DECL);
+extern void vec_stack_free (void *);
+
+/* Reallocate an array of elements with prefix. */
+template<typename T, enum vec_allocation_t A>
+extern vec_t<T> *vec_reserve (vec_t<T> *, int MEM_STAT_DECL);
+
+template<typename T, enum vec_allocation_t A>
+extern vec_t<T> *vec_reserve_exact (vec_t<T> *, int MEM_STAT_DECL);
+
+extern void dump_vec_loc_statistics (void);
+extern void ggc_free (void *);
+extern void vec_heap_free (void *);
+
+
/* Macros to invoke API calls. A single macro works for both pointer
and object vectors, but the argument and return types might well be
different. In each macro, T is the typedef of the vector elements,
@@ -148,7 +296,14 @@ along with GCC; see the file COPYING3. If not see
Return the number of active elements in V. V can be NULL, in which
case zero is returned. */
-#define VEC_length(T,V) (VEC_OP(T,base,length)(VEC_BASE(V)))
+#define VEC_length(T,V) (VEC_length_1<T> (V))
+
+template<typename T>
+static inline unsigned
+VEC_length_1 (const vec_t<T> *vec_)
+{
+ return vec_ ? vec_->prefix.num : 0;
+}
/* Check if vector is empty
@@ -156,7 +311,30 @@ along with GCC; see the file COPYING3. If not see
Return nonzero if V is an empty vector (or V is NULL), zero otherwise. */
-#define VEC_empty(T,V) (VEC_length (T,V) == 0)
+#define VEC_empty(T,V) (VEC_empty_1<T> (V))
+
+template<typename T>
+static inline bool
+VEC_empty_1 (const vec_t<T> *vec_)
+{
+ return VEC_length (T, vec_) == 0;
+}
+
+
+/* Get the address of the array of elements
+ T *VEC_T_address (VEC(T) v)
+
+ If you need to directly manipulate the array (for instance, you
+ want to feed it to qsort), use this accessor. */
+
+#define VEC_address(T,V) (VEC_address_1<T> (V))
+
+template<typename T>
+static inline T *
+VEC_address_1 (vec_t<T> *vec_)
+{
+ return vec_ ? vec_->vec : 0;
+}
/* Get the final element of the vector.
@@ -166,16 +344,42 @@ along with GCC; see the file COPYING3. If not see
Return the final element. V must not be empty. */
-#define VEC_last(T,V) (VEC_OP(T,base,last)(VEC_BASE(V) VEC_CHECK_INFO))
+#define VEC_last(T,V) (VEC_last_1<T> (V VEC_CHECK_INFO))
+
+template<typename T>
+static inline T&
+VEC_last_1 (vec_t<T> *vec_ VEC_CHECK_DECL)
+{
+ VEC_ASSERT (vec_ && vec_->prefix.num, "last", T, base);
+ return vec_->vec[vec_->prefix.num - 1];
+}
+
/* Index into vector
T VEC_T_index(VEC(T) *v, unsigned ix); // Integer
T VEC_T_index(VEC(T) *v, unsigned ix); // Pointer
T *VEC_T_index(VEC(T) *v, unsigned ix); // Object
- Return the IX'th element. If IX must be in the domain of V. */
+ Return the IX'th element. IX must be in the domain of V. */
+
+#define VEC_index(T,V,I) (VEC_index_1<T> (V, I VEC_CHECK_INFO))
+
+template<typename T>
+static inline T&
+VEC_index_1 (vec_t<T> *vec_, unsigned ix_ VEC_CHECK_DECL)
+{
+ VEC_ASSERT (vec_ && ix_ < vec_->prefix.num, "index", T, base);
+ return vec_->vec[ix_];
+}
+
+template<typename T>
+static inline const T&
+VEC_index_1 (const vec_t<T> *vec_, unsigned ix_ VEC_CHECK_DECL)
+{
+ VEC_ASSERT (vec_ && ix_ < vec_->prefix.num, "index", T, base);
+ return vec_->vec[ix_];
+}
-#define VEC_index(T,V,I) (VEC_OP(T,base,index)(VEC_BASE(V),I VEC_CHECK_INFO))
/* Iterate over vector
int VEC_T_iterate(VEC(T) *v, unsigned ix, T &ptr); // Integer
@@ -189,7 +393,39 @@ along with GCC; see the file COPYING3. If not see
for (ix = 0; VEC_iterate(T,v,ix,ptr); ix++)
continue; */
-#define VEC_iterate(T,V,I,P) (VEC_OP(T,base,iterate)(VEC_BASE(V),I,&(P)))
+#define VEC_iterate(T,V,I,P) (VEC_iterate_1<T> (V, I, &(P)))
+
+template<typename T>
+static inline bool
+VEC_iterate_1 (const vec_t<T> *vec_, unsigned ix_, T *ptr)
+{
+ if (vec_ && ix_ < vec_->prefix.num)
+ {
+ *ptr = vec_->vec[ix_];
+ return true;
+ }
+ else
+ {
+ *ptr = 0;
+ return false;
+ }
+}
+
+template<typename T>
+static inline bool
+VEC_iterate_1 (vec_t<T> *vec_, unsigned ix_, T **ptr)
+{
+ if (vec_ && ix_ < vec_->prefix.num)
+ {
+ *ptr = &vec_->vec[ix_];
+ return true;
+ }
+ else
+ {
+ *ptr = 0;
+ return false;
+ }
+}
/* Convenience macro for forward iteration. */
@@ -208,31 +444,99 @@ along with GCC; see the file COPYING3. If not see
VEC_iterate (T, (V), (I), (P)); \
(I)--)
+
+/* Use these to determine the required size and initialization of a
+ vector embedded within another structure (as the final member).
+
+ size_t VEC_T_embedded_size(int reserve);
+ void VEC_T_embedded_init(VEC(T) *v, int reserve);
+
+ These allow the caller to perform the memory allocation. */
+
+#define VEC_embedded_size(T,N) (VEC_embedded_size_1<T> (N))
+
+template<typename T>
+static inline size_t
+VEC_embedded_size_1 (int alloc_)
+{
+ return offsetof (vec_t<T>, vec) + alloc_ * sizeof (T);
+}
+
+#define VEC_embedded_init(T,O,N) (VEC_embedded_init_1<T> (O, N))
+
+template<typename T>
+static inline void
+VEC_embedded_init_1 (vec_t<T> *vec_, int alloc_)
+{
+ vec_->prefix.num = 0;
+ vec_->prefix.alloc = alloc_;
+}
+
+
/* Allocate new vector.
VEC(T,A) *VEC_T_A_alloc(int reserve);
Allocate a new vector with space for RESERVE objects. If RESERVE
- is zero, NO vector is created. */
+ is zero, NO vector is created.
+
+ We support a vector which starts out with space on the stack and
+ switches to heap space when forced to reallocate. This works a
+ little differently. In the case of stack vectors, VEC_alloc will
+ expand to a call to VEC_alloc_1 that calls XALLOCAVAR to request the
+ initial allocation. This uses alloca to get the initial space.
+ Since alloca can not be usefully called in an inline function,
+ VEC_alloc must always be a macro.
+
+ Only the initial allocation will be made using alloca, so pass a
+ reasonable estimate that doesn't use too much stack space; don't
+ pass zero. Don't return a VEC(TYPE,stack) vector from the function
+ which allocated it. */
+
+#define VEC_alloc(T,A,N) \
+ ((A == stack) \
+ ? VEC_alloc_1 (N, \
+ XALLOCAVAR (vec_t<T>, \
+ VEC_embedded_size_1<T> (N))) \
+ : VEC_alloc_1<T, A> (N MEM_STAT_INFO))
+
+template<typename T, enum vec_allocation_t A>
+static inline vec_t<T> *
+VEC_alloc_1 (int alloc_ MEM_STAT_DECL)
+{
+ return vec_reserve_exact<T, A> (NULL, alloc_ PASS_MEM_STAT);
+}
+
+template<typename T>
+static inline vec_t<T> *
+VEC_alloc_1 (int alloc_, vec_t<T> *space)
+{
+ return (vec_t<T> *) vec_stack_p_reserve_exact_1 (alloc_, space);
+}
-#define VEC_alloc(T,A,N) (VEC_OP(T,A,alloc)(N MEM_STAT_INFO))
/* Free a vector.
void VEC_T_A_free(VEC(T,A) *&);
Free a vector and set it to NULL. */
-#define VEC_free(T,A,V) (VEC_OP(T,A,free)(&V))
+#define VEC_free(T,A,V) (VEC_free_1<T, A> (&V))
-/* Use these to determine the required size and initialization of a
- vector embedded within another structure (as the final member).
-
- size_t VEC_T_embedded_size(int reserve);
- void VEC_T_embedded_init(VEC(T) *v, int reserve);
-
- These allow the caller to perform the memory allocation. */
+template<typename T, enum vec_allocation_t A>
+static inline void
+VEC_free_1 (vec_t<T> **vec_)
+{
+ if (*vec_)
+ {
+ if (A == heap)
+ vec_heap_free (*vec_);
+ else if (A == gc)
+ ggc_free (*vec_);
+ else if (A == stack)
+ vec_stack_free (*vec_);
+ }
+ *vec_ = NULL;
+}
-#define VEC_embedded_size(T,N) (VEC_OP(T,base,embedded_size)(N))
-#define VEC_embedded_init(T,O,N) (VEC_OP(T,base,embedded_init)(VEC_BASE(O),N))
/* Copy a vector.
VEC(T,A) *VEC_T_A_copy(VEC(T) *);
@@ -240,7 +544,24 @@ along with GCC; see the file COPYING3. If not see
Copy the live elements of a vector into a new vector. The new and
old vectors need not be allocated by the same mechanism. */
-#define VEC_copy(T,A,V) (VEC_OP(T,A,copy)(VEC_BASE(V) MEM_STAT_INFO))
+#define VEC_copy(T,A,V) (VEC_copy_1<T, A> (V MEM_STAT_INFO))
+
+template<typename T, enum vec_allocation_t A>
+static inline vec_t<T> *
+VEC_copy_1 (vec_t<T> *vec_ MEM_STAT_DECL)
+{
+ size_t len_ = vec_ ? vec_->prefix.num : 0;
+ vec_t<T> *new_vec_ = NULL;
+
+ if (len_)
+ {
+ new_vec_ = vec_reserve_exact<T, A> (NULL, len_ PASS_MEM_STAT);
+ new_vec_->prefix.num = len_;
+ memcpy (new_vec_->vec, vec_->vec, sizeof (T) * len_);
+ }
+ return new_vec_;
+}
+
/* Determine if a vector has additional capacity.
@@ -252,8 +573,18 @@ along with GCC; see the file COPYING3. If not see
nonzero in exactly the same circumstances that VEC_T_reserve
will. */
-#define VEC_space(T,V,R) \
- (VEC_OP(T,base,space)(VEC_BASE(V),R VEC_CHECK_INFO))
+#define VEC_space(T,V,R) (VEC_space_1<T> (V, R VEC_CHECK_INFO))
+
+template<typename T>
+static inline int
+VEC_space_1 (vec_t<T> *vec_, int alloc_ VEC_CHECK_DECL)
+{
+ VEC_ASSERT (alloc_ >= 0, "space", T, base);
+ return vec_
+ ? vec_->prefix.alloc - vec_->prefix.num >= (unsigned)alloc_
+ : !alloc_;
+}
+
/* Reserve space.
int VEC_T_A_reserve(VEC(T,A) *&v, int reserve);
@@ -264,7 +595,20 @@ along with GCC; see the file COPYING3. If not see
occurred. */
#define VEC_reserve(T,A,V,R) \
- (VEC_OP(T,A,reserve)(&(V),R VEC_CHECK_INFO MEM_STAT_INFO))
+ (VEC_reserve_1<T, A> (&(V), (int)(R) VEC_CHECK_INFO MEM_STAT_INFO))
+
+template<typename T, enum vec_allocation_t A>
+static inline int
+VEC_reserve_1 (vec_t<T> **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL)
+{
+ int extend = !VEC_space_1 (*vec_, alloc_ VEC_CHECK_PASS);
+
+ if (extend)
+ *vec_ = vec_reserve<T, A> (*vec_, alloc_ PASS_MEM_STAT);
+
+ return extend;
+}
+
/* Reserve space exactly.
int VEC_T_A_reserve_exact(VEC(T,A) *&v, int reserve);
@@ -275,7 +619,20 @@ along with GCC; see the file COPYING3. If not see
occurred. */
#define VEC_reserve_exact(T,A,V,R) \
- (VEC_OP(T,A,reserve_exact)(&(V),R VEC_CHECK_INFO MEM_STAT_INFO))
+ (VEC_reserve_exact_1<T, A> (&(V), R VEC_CHECK_INFO MEM_STAT_INFO))
+
+template<typename T, enum vec_allocation_t A>
+static inline int
+VEC_reserve_exact_1 (vec_t<T> **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL)
+{
+ int extend = !VEC_space_1 (*vec_, alloc_ VEC_CHECK_PASS);
+
+ if (extend)
+ *vec_ = vec_reserve_exact<T, A> (*vec_, alloc_ PASS_MEM_STAT);
+
+ return extend;
+}
+
/* Copy elements with no reallocation
void VEC_T_splice (VEC(T) *dst, VEC(T) *src); // Integer
@@ -287,8 +644,23 @@ along with GCC; see the file COPYING3. If not see
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))
+#define VEC_splice(T,DST,SRC) (VEC_splice_1<T> (DST, SRC VEC_CHECK_INFO))
+
+template<typename T>
+static inline void
+VEC_splice_1 (vec_t<T> *dst_, vec_t<T> *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_;
+ }
+}
+
/* Copy elements with reallocation
void VEC_T_safe_splice (VEC(T,A) *&dst, VEC(T) *src); // Integer
@@ -301,7 +673,21 @@ along with GCC; see the file COPYING3. If not see
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))
+ (VEC_safe_splice_1<T, A> (&(DST), SRC VEC_CHECK_INFO MEM_STAT_INFO))
+
+template<typename T, enum vec_allocation_t A>
+static inline void
+VEC_safe_splice_1 (vec_t<T> **dst_, vec_t<T> *src_ VEC_CHECK_DECL MEM_STAT_DECL)
+{
+ if (src_)
+ {
+ VEC_reserve_exact_1<T, A> (dst_, src_->prefix.num
+ VEC_CHECK_PASS MEM_STAT_INFO);
+
+ VEC_splice_1 (*dst_, src_ VEC_CHECK_PASS);
+ }
+}
+
/* Push object with no reallocation
T *VEC_T_quick_push (VEC(T) *v, T obj); // Integer
@@ -313,8 +699,31 @@ along with GCC; see the file COPYING3. If not see
case NO initialization is performed. There must
be sufficient space in the vector. */
-#define VEC_quick_push(T,V,O) \
- (VEC_OP(T,base,quick_push)(VEC_BASE(V),O VEC_CHECK_INFO))
+#define VEC_quick_push(T,V,O) (VEC_quick_push_1<T> (V, O VEC_CHECK_INFO))
+
+template<typename T>
+static inline T &
+VEC_quick_push_1 (vec_t<T> *vec_, T obj_ VEC_CHECK_DECL)
+{
+ VEC_ASSERT (vec_->prefix.num < vec_->prefix.alloc, "push", T, base);
+ vec_->vec[vec_->prefix.num] = obj_;
+ T &val_ = vec_->vec[vec_->prefix.num];
+ vec_->prefix.num++;
+ return val_;
+}
+
+template<typename T>
+static inline T *
+VEC_quick_push_1 (vec_t<T> *vec_, const T *ptr_ VEC_CHECK_DECL)
+{
+ T *slot_;
+ VEC_ASSERT (vec_->prefix.num < vec_->prefix.alloc, "push", T, base);
+ slot_ = &vec_->vec[vec_->prefix.num++];
+ if (ptr_)
+ *slot_ = *ptr_;
+ return slot_;
+}
+
/* Push object with reallocation
T *VEC_T_A_safe_push (VEC(T,A) *&v, T obj); // Integer
@@ -326,7 +735,24 @@ along with GCC; see the file COPYING3. If not see
case NO initialization is performed. Reallocates V, if needed. */
#define VEC_safe_push(T,A,V,O) \
- (VEC_OP(T,A,safe_push)(&(V),O VEC_CHECK_INFO MEM_STAT_INFO))
+ (VEC_safe_push_1<T, A> (&(V), O VEC_CHECK_INFO MEM_STAT_INFO))
+
+template<typename T, enum vec_allocation_t A>
+static inline T &
+VEC_safe_push_1 (vec_t<T> **vec_, T obj_ VEC_CHECK_DECL MEM_STAT_DECL)
+{
+ VEC_reserve_1<T, A> (vec_, 1 VEC_CHECK_PASS PASS_MEM_STAT);
+ return VEC_quick_push_1 (*vec_, obj_ VEC_CHECK_PASS);
+}
+
+template<typename T, enum vec_allocation_t A>
+static inline T *
+VEC_safe_push_1 (vec_t<T> **vec_, const T *ptr_ VEC_CHECK_DECL MEM_STAT_DECL)
+{
+ VEC_reserve_1<T, A> (vec_, 1 VEC_CHECK_PASS PASS_MEM_STAT);
+ return VEC_quick_push_1 (*vec_, ptr_ VEC_CHECK_PASS);
+}
+
/* Pop element off end
T VEC_T_pop (VEC(T) *v); // Integer
@@ -336,7 +762,16 @@ along with GCC; see the file COPYING3. If not see
Pop the last element off the end. Returns the element popped, for
pointer vectors. */
-#define VEC_pop(T,V) (VEC_OP(T,base,pop)(VEC_BASE(V) VEC_CHECK_INFO))
+#define VEC_pop(T,V) (VEC_pop_1<T> (V VEC_CHECK_INFO))
+
+template<typename T>
+static inline T&
+VEC_pop_1 (vec_t<T> *vec_ VEC_CHECK_DECL)
+{
+ VEC_ASSERT (vec_->prefix.num, "pop", T, base);
+ return vec_->vec[--vec_->prefix.num];
+}
+
/* Truncate to specific length
void VEC_T_truncate (VEC(T) *v, unsigned len);
@@ -344,8 +779,18 @@ along with GCC; see the file COPYING3. If not see
Set the length as specified. The new length must be less than or
equal to the current length. This is an O(1) operation. */
-#define VEC_truncate(T,V,I) \
- (VEC_OP(T,base,truncate)(VEC_BASE(V),I VEC_CHECK_INFO))
+#define VEC_truncate(T,V,I) \
+ (VEC_truncate_1<T> (V, (unsigned)(I) VEC_CHECK_INFO))
+
+template<typename T>
+static inline void
+VEC_truncate_1 (vec_t<T> *vec_, unsigned size_ VEC_CHECK_DECL)
+{
+ VEC_ASSERT (vec_ ? vec_->prefix.num >= size_ : !size_, "truncate", T, base);
+ if (vec_)
+ vec_->prefix.num = size_;
+}
+
/* Grow to a specific length.
void VEC_T_A_safe_grow (VEC(T,A) *&v, int len);
@@ -355,7 +800,20 @@ along with GCC; see the file COPYING3. If not see
uninitialized. */
#define VEC_safe_grow(T,A,V,I) \
- (VEC_OP(T,A,safe_grow)(&(V),I VEC_CHECK_INFO MEM_STAT_INFO))
+ (VEC_safe_grow_1<T, A> (&(V), (int)(I) VEC_CHECK_INFO MEM_STAT_INFO))
+
+template<typename T, enum vec_allocation_t A>
+static inline void
+VEC_safe_grow_1 (vec_t<T> **vec_, int size_ VEC_CHECK_DECL MEM_STAT_DECL)
+{
+ VEC_ASSERT (size_ >= 0 && VEC_length (T, *vec_) <= (unsigned)size_,
+ "grow", T, A);
+ VEC_reserve_exact_1<T, A> (vec_,
+ size_ - (int)(*vec_ ? (*vec_)->prefix.num : 0)
+ VEC_CHECK_PASS PASS_MEM_STAT);
+ (*vec_)->prefix.num = size_;
+}
+
/* Grow to a specific length.
void VEC_T_A_safe_grow_cleared (VEC(T,A) *&v, int len);
@@ -364,8 +822,21 @@ along with GCC; see the file COPYING3. If not see
long or longer than the current length. The new elements are
initialized to zero. */
-#define VEC_safe_grow_cleared(T,A,V,I) \
- (VEC_OP(T,A,safe_grow_cleared)(&(V),I VEC_CHECK_INFO MEM_STAT_INFO))
+#define VEC_safe_grow_cleared(T,A,V,I) \
+ (VEC_safe_grow_cleared_1<T,A> (&(V), (int)(I) \
+ VEC_CHECK_INFO MEM_STAT_INFO))
+
+template<typename T, enum vec_allocation_t A>
+static inline void
+VEC_safe_grow_cleared_1 (vec_t<T> **vec_, int size_ VEC_CHECK_DECL
+ MEM_STAT_DECL)
+{
+ int oldsize = VEC_length (T, *vec_);
+ VEC_safe_grow_1<T, A> (vec_, size_ VEC_CHECK_PASS PASS_MEM_STAT);
+ memset (&(VEC_address (T, *vec_)[oldsize]), 0,
+ sizeof (T) * (size_ - oldsize));
+}
+
/* Replace element
T VEC_T_replace (VEC(T) *v, unsigned ix, T val); // Integer
@@ -379,20 +850,57 @@ along with GCC; see the file COPYING3. If not see
performed. */
#define VEC_replace(T,V,I,O) \
- (VEC_OP(T,base,replace)(VEC_BASE(V),I,O VEC_CHECK_INFO))
+ (VEC_replace_1<T> (V, (unsigned)(I), O VEC_CHECK_INFO))
+
+template<typename T>
+static inline T&
+VEC_replace_1 (vec_t<T> *vec_, unsigned ix_, T obj_ VEC_CHECK_DECL)
+{
+ VEC_ASSERT (ix_ < vec_->prefix.num, "replace", T, base);
+ vec_->vec[ix_] = obj_;
+ return vec_->vec[ix_];
+}
+
/* Insert object with no reallocation
- T *VEC_T_quick_insert (VEC(T) *v, unsigned ix, T val); // Integer
- T *VEC_T_quick_insert (VEC(T) *v, unsigned ix, T val); // Pointer
- T *VEC_T_quick_insert (VEC(T) *v, unsigned ix, T *val); // Object
+ void VEC_T_quick_insert (VEC(T) *v, unsigned ix, T val); // Integer
+ void VEC_T_quick_insert (VEC(T) *v, unsigned ix, T val); // Pointer
+ void VEC_T_quick_insert (VEC(T) *v, unsigned ix, T *val); // Object
- Insert an element, VAL, at the IXth position of V. Return a pointer
- to the slot created. For vectors of object, the new value can be
- NULL, in which case no initialization of the inserted slot takes
- place. There must be sufficient space. */
+ Insert an element, VAL, at the IXth position of V. For vectors of
+ object, the new value can be NULL, in which case no initialization
+ of the inserted slot takes place. There must be sufficient space. */
#define VEC_quick_insert(T,V,I,O) \
- (VEC_OP(T,base,quick_insert)(VEC_BASE(V),I,O VEC_CHECK_INFO))
+ (VEC_quick_insert_1<T> (V,I,O VEC_CHECK_INFO))
+
+template<typename T>
+static inline void
+VEC_quick_insert_1 (vec_t<T> *vec_, unsigned ix_, T obj_ VEC_CHECK_DECL)
+{
+ T *slot_;
+
+ 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_->prefix.num++ - ix_) * sizeof (T));
+ *slot_ = obj_;
+}
+
+template<typename T>
+static inline void
+VEC_quick_insert_1 (vec_t<T> *vec_, unsigned ix_, const T *ptr_ VEC_CHECK_DECL)
+{
+ T *slot_;
+
+ 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_->prefix.num++ - ix_) * sizeof (T));
+ if (ptr_)
+ *slot_ = *ptr_;
+}
+
/* Insert object with reallocation
T *VEC_T_A_safe_insert (VEC(T,A) *&v, unsigned ix, T val); // Integer
@@ -405,31 +913,70 @@ along with GCC; see the file COPYING3. If not see
place. Reallocate V, if necessary. */
#define VEC_safe_insert(T,A,V,I,O) \
- (VEC_OP(T,A,safe_insert)(&(V),I,O VEC_CHECK_INFO MEM_STAT_INFO))
+ (VEC_safe_insert_1<T, A> (&(V),I,O VEC_CHECK_INFO MEM_STAT_INFO))
+
+template<typename T, enum vec_allocation_t A>
+static inline void
+VEC_safe_insert_1 (vec_t<T> **vec_, unsigned ix_, T obj_
+ VEC_CHECK_DECL MEM_STAT_DECL)
+{
+ VEC_reserve_1<T, A> (vec_, 1 VEC_CHECK_PASS PASS_MEM_STAT);
+ VEC_quick_insert_1 (*vec_, ix_, obj_ VEC_CHECK_PASS);
+}
+
+template<typename T, enum vec_allocation_t A>
+static inline void
+VEC_safe_insert_1 (vec_t<T> **vec_, unsigned ix_, T *ptr_
+ VEC_CHECK_DECL MEM_STAT_DECL)
+{
+ VEC_reserve_1<T, A> (vec_, 1 VEC_CHECK_PASS PASS_MEM_STAT);
+ VEC_quick_insert_1 (*vec_, ix_, ptr_ VEC_CHECK_PASS);
+}
+
+
/* Remove element retaining order
- T VEC_T_ordered_remove (VEC(T) *v, unsigned ix); // Integer
- T VEC_T_ordered_remove (VEC(T) *v, unsigned ix); // Pointer
+ void VEC_T_ordered_remove (VEC(T) *v, unsigned ix); // Integer
+ void VEC_T_ordered_remove (VEC(T) *v, unsigned ix); // Pointer
void VEC_T_ordered_remove (VEC(T) *v, unsigned ix); // Object
Remove an element from the IXth position of V. Ordering of
- remaining elements is preserved. For pointer vectors returns the
- removed object. This is an O(N) operation due to a memmove. */
+ remaining elements is preserved. This is an O(N) operation due to
+ a memmove. */
#define VEC_ordered_remove(T,V,I) \
- (VEC_OP(T,base,ordered_remove)(VEC_BASE(V),I VEC_CHECK_INFO))
+ (VEC_ordered_remove_1<T> (V,I VEC_CHECK_INFO))
+
+template<typename T>
+static inline void
+VEC_ordered_remove_1 (vec_t<T> *vec_, unsigned ix_ VEC_CHECK_DECL)
+{
+ T *slot_;
+ VEC_ASSERT (ix_ < vec_->prefix.num, "remove", T, base);
+ slot_ = &vec_->vec[ix_];
+ memmove (slot_, slot_ + 1, (--vec_->prefix.num - ix_) * sizeof (T));
+}
+
/* Remove element destroying order
- T VEC_T_unordered_remove (VEC(T) *v, unsigned ix); // Integer
- T VEC_T_unordered_remove (VEC(T) *v, unsigned ix); // Pointer
+ void VEC_T_unordered_remove (VEC(T) *v, unsigned ix); // Integer
+ void VEC_T_unordered_remove (VEC(T) *v, unsigned ix); // Pointer
void VEC_T_unordered_remove (VEC(T) *v, unsigned ix); // Object
- Remove an element from the IXth position of V. Ordering of
- remaining elements is destroyed. For pointer vectors returns the
- removed object. This is an O(1) operation. */
+ Remove an element from the IXth position of V. Ordering of
+ remaining elements is destroyed. This is an O(1) operation. */
#define VEC_unordered_remove(T,V,I) \
- (VEC_OP(T,base,unordered_remove)(VEC_BASE(V),I VEC_CHECK_INFO))
+ (VEC_unordered_remove_1<T> (V,I VEC_CHECK_INFO))
+
+template<typename T>
+static inline void
+VEC_unordered_remove_1 (vec_t<T> *vec_, unsigned ix_ VEC_CHECK_DECL)
+{
+ VEC_ASSERT (ix_ < vec_->prefix.num, "remove", T, base);
+ vec_->vec[ix_] = vec_->vec[--vec_->prefix.num];
+}
+
/* Remove a block of elements
void VEC_T_block_remove (VEC(T) *v, unsigned ix, unsigned len);
@@ -438,22 +985,27 @@ along with GCC; see the file COPYING3. If not see
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))
+ (VEC_block_remove_1<T> (V, I, L VEC_CHECK_INFO))
-/* Get the address of the array of elements
- T *VEC_T_address (VEC(T) v)
-
- If you need to directly manipulate the array (for instance, you
- want to feed it to qsort), use this accessor. */
+template<typename T>
+static inline void
+VEC_block_remove_1 (vec_t<T> *vec_, unsigned ix_, unsigned len_ VEC_CHECK_DECL)
+{
+ T *slot_;
+ VEC_ASSERT (ix_ + len_ <= vec_->prefix.num, "block_remove", T, base);
+ slot_ = &vec_->vec[ix_];
+ vec_->prefix.num -= len_;
+ memmove (slot_, slot_ + len_, (vec_->prefix.num - ix_) * sizeof (T));
+}
-#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), \
+#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
@@ -466,955 +1018,140 @@ along with GCC; see the file COPYING3. If not see
changing the ordering of V. LESSTHAN is a function that returns
true if the first argument is strictly less than the second. */
-#define VEC_lower_bound(T,V,O,LT) \
- (VEC_OP(T,base,lower_bound)(VEC_BASE(V),O,LT VEC_CHECK_INFO))
+#define VEC_lower_bound(T,V,O,LT) \
+ (VEC_lower_bound_1<T> (V, O, LT VEC_CHECK_INFO))
-/* Reallocate an array of elements with prefix. */
-extern void *vec_gc_p_reserve (void *, int MEM_STAT_DECL);
-extern void *vec_gc_p_reserve_exact (void *, int MEM_STAT_DECL);
-extern void *vec_gc_o_reserve (void *, int, size_t, size_t MEM_STAT_DECL);
-extern void *vec_gc_o_reserve_exact (void *, int, size_t, size_t
- MEM_STAT_DECL);
-extern void ggc_free (void *);
-#define vec_gc_free(V) ggc_free (V)
-extern void *vec_heap_p_reserve (void *, int MEM_STAT_DECL);
-extern void *vec_heap_p_reserve_exact (void *, int MEM_STAT_DECL);
-extern void *vec_heap_o_reserve (void *, int, size_t, size_t MEM_STAT_DECL);
-extern void *vec_heap_o_reserve_exact (void *, int, size_t, size_t
- MEM_STAT_DECL);
-extern void dump_vec_loc_statistics (void);
-extern void vec_heap_free (void *);
-
-#if ENABLE_CHECKING
-#define VEC_CHECK_INFO ,__FILE__,__LINE__,__FUNCTION__
-#define VEC_CHECK_DECL ,const char *file_,unsigned line_,const char *function_
-#define VEC_CHECK_PASS ,file_,line_,function_
-
-#define VEC_ASSERT(EXPR,OP,T,A) \
- (void)((EXPR) ? 0 : (VEC_ASSERT_FAIL(OP,VEC(T,A)), 0))
-
-extern void vec_assert_fail (const char *, const char * VEC_CHECK_DECL)
- ATTRIBUTE_NORETURN;
-#define VEC_ASSERT_FAIL(OP,VEC) vec_assert_fail (OP,#VEC VEC_CHECK_PASS)
-#else
-#define VEC_CHECK_INFO
-#define VEC_CHECK_DECL
-#define VEC_CHECK_PASS
-#define VEC_ASSERT(EXPR,OP,T,A) (void)(EXPR)
-#endif
-
-/* Note: gengtype has hardwired knowledge of the expansions of the
- 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
+template<typename T>
+static inline unsigned
+VEC_lower_bound_1 (vec_t<T> *vec_, T obj_,
+ bool (*lessthan_)(T, T) VEC_CHECK_DECL)
{
- unsigned num;
- unsigned alloc;
-} vec_prefix;
-
-#define VEC(T,A) VEC_##T##_##A
-#define VEC_OP(T,A,OP) VEC_##T##_##A##_##OP
-
-/* Base of vector type, not user visible. */
-#define VEC_T(T,B) \
-typedef struct VEC(T,B) \
-{ \
- struct vec_prefix prefix; \
- T vec[1]; \
-} VEC(T,B)
-
-#define VEC_T_GTY(T,B) \
-typedef struct GTY(()) VEC(T,B) \
-{ \
- struct vec_prefix prefix; \
- T GTY ((length ("%h.prefix.num"))) vec[1]; \
-} VEC(T,B)
-
-#define VEC_T_GTY_ATOMIC(T,B) \
-typedef struct GTY(()) VEC(T,B) \
-{ \
- struct vec_prefix prefix; \
- T GTY ((atomic)) vec[1]; \
-} VEC(T,B)
-
-/* Derived vector type, user visible. */
-#define VEC_TA_GTY(T,B,A,GTY) \
-typedef struct GTY VEC(T,A) \
-{ \
- VEC(T,B) base; \
-} VEC(T,A)
-
-#define VEC_TA(T,B,A) \
-typedef struct VEC(T,A) \
-{ \
- VEC(T,B) base; \
-} 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) \
-static inline void VEC_OP (T,must_be,integral_type) (void) \
-{ \
- (void)~(T)0; \
-} \
- \
-VEC_T(T,base); \
-VEC_TA(T,base,none); \
-DEF_VEC_FUNC_P(T) \
-struct vec_swallow_trailing_semi
-#define DEF_VEC_ALLOC_I(T,A) \
-VEC_TA(T,base,A); \
-DEF_VEC_ALLOC_FUNC_I(T,A) \
-DEF_VEC_NONALLOC_FUNCS_I(T,A) \
-struct vec_swallow_trailing_semi
-
-/* Vector of pointer to object. */
-#define DEF_VEC_P(T) \
-static inline void VEC_OP (T,must_be,pointer_type) (void) \
-{ \
- (void)((T)1 == (void *)1); \
-} \
- \
-VEC_T_GTY(T,base); \
-VEC_TA(T,base,none); \
-DEF_VEC_FUNC_P(T) \
-struct vec_swallow_trailing_semi
-#define DEF_VEC_ALLOC_P(T,A) \
-VEC_TA(T,base,A); \
-DEF_VEC_ALLOC_FUNC_P(T,A) \
-DEF_VEC_NONALLOC_FUNCS_P(T,A) \
-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_->prefix.num : 0; \
-} \
- \
-static inline T VEC_OP (T,base,last) \
- (const VEC(T,base) *vec_ VEC_CHECK_DECL) \
-{ \
- VEC_ASSERT (vec_ && vec_->prefix.num, "last", T, base); \
- \
- 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_->prefix.num, "index", T, base); \
- \
- return vec_->vec[ix_]; \
-} \
- \
-static inline int VEC_OP (T,base,iterate) \
- (const VEC(T,base) *vec_, unsigned ix_, T *ptr) \
-{ \
- if (vec_ && ix_ < vec_->prefix.num) \
- { \
- *ptr = vec_->vec[ix_]; \
- return 1; \
- } \
- else \
- { \
- *ptr = (T) 0; \
- return 0; \
- } \
-} \
- \
-static inline size_t VEC_OP (T,base,embedded_size) \
- (int alloc_) \
-{ \
- return offsetof (VEC(T,base),vec) + alloc_ * sizeof(T); \
-} \
- \
-static inline void VEC_OP (T,base,embedded_init) \
- (VEC(T,base) *vec_, int 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_->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) \
- (VEC(T,base) *vec_, T obj_ VEC_CHECK_DECL) \
-{ \
- T *slot_; \
- \
- VEC_ASSERT (vec_->prefix.num < vec_->prefix.alloc, "push", T, base); \
- slot_ = &vec_->vec[vec_->prefix.num++]; \
- *slot_ = obj_; \
- \
- return slot_; \
-} \
- \
-static inline T VEC_OP (T,base,pop) (VEC(T,base) *vec_ VEC_CHECK_DECL) \
-{ \
- T obj_; \
- \
- VEC_ASSERT (vec_->prefix.num, "pop", T, base); \
- obj_ = vec_->vec[--vec_->prefix.num]; \
- \
- return obj_; \
-} \
- \
-static inline void VEC_OP (T,base,truncate) \
- (VEC(T,base) *vec_, unsigned size_ VEC_CHECK_DECL) \
-{ \
- VEC_ASSERT (vec_ ? vec_->prefix.num >= size_ : !size_, "truncate", T, base); \
- if (vec_) \
- vec_->prefix.num = size_; \
-} \
- \
-static inline T VEC_OP (T,base,replace) \
- (VEC(T,base) *vec_, unsigned ix_, T obj_ VEC_CHECK_DECL) \
-{ \
- T old_obj_; \
- \
- VEC_ASSERT (ix_ < vec_->prefix.num, "replace", T, base); \
- old_obj_ = vec_->vec[ix_]; \
- vec_->vec[ix_] = obj_; \
- \
- return old_obj_; \
-} \
- \
-static inline T *VEC_OP (T,base,quick_insert) \
- (VEC(T,base) *vec_, unsigned ix_, T obj_ VEC_CHECK_DECL) \
-{ \
- T *slot_; \
- \
- 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_->prefix.num++ - ix_) * sizeof (T)); \
- *slot_ = obj_; \
- \
- return slot_; \
-} \
- \
-static inline T VEC_OP (T,base,ordered_remove) \
- (VEC(T,base) *vec_, unsigned ix_ VEC_CHECK_DECL) \
-{ \
- T *slot_; \
- T obj_; \
- \
- VEC_ASSERT (ix_ < vec_->prefix.num, "remove", T, base); \
- slot_ = &vec_->vec[ix_]; \
- obj_ = *slot_; \
- memmove (slot_, slot_ + 1, (--vec_->prefix.num - ix_) * sizeof (T)); \
- \
- return obj_; \
-} \
- \
-static inline T VEC_OP (T,base,unordered_remove) \
- (VEC(T,base) *vec_, unsigned ix_ VEC_CHECK_DECL) \
-{ \
- T *slot_; \
- T obj_; \
- \
- VEC_ASSERT (ix_ < vec_->prefix.num, "remove", T, base); \
- slot_ = &vec_->vec[ix_]; \
- obj_ = *slot_; \
- *slot_ = vec_->vec[--vec_->prefix.num]; \
- \
- return obj_; \
-} \
- \
-static inline void VEC_OP (T,base,block_remove) \
- (VEC(T,base) *vec_, unsigned ix_, unsigned len_ VEC_CHECK_DECL) \
-{ \
- T *slot_; \
- \
- VEC_ASSERT (ix_ + len_ <= vec_->prefix.num, "block_remove", T, base); \
- slot_ = &vec_->vec[ix_]; \
- vec_->prefix.num -= len_; \
- memmove (slot_, slot_ + len_, (vec_->prefix.num - ix_) * sizeof (T)); \
-} \
- \
-static inline T *VEC_OP (T,base,address) \
- (VEC(T,base) *vec_) \
-{ \
- return vec_ ? vec_->vec : 0; \
-} \
- \
-static inline unsigned VEC_OP (T,base,lower_bound) \
- (VEC(T,base) *vec_, const T obj_, \
- bool (*lessthan_)(const T, const T) VEC_CHECK_DECL) \
-{ \
- unsigned int len_ = VEC_OP (T,base, length) (vec_); \
- unsigned int half_, middle_; \
- unsigned int first_ = 0; \
- while (len_ > 0) \
- { \
- T middle_elem_; \
- half_ = len_ >> 1; \
- middle_ = first_; \
- middle_ += half_; \
- middle_elem_ = VEC_OP (T,base,index) (vec_, middle_ VEC_CHECK_PASS); \
- if (lessthan_ (middle_elem_, obj_)) \
- { \
- first_ = middle_; \
- ++first_; \
- len_ = len_ - half_ - 1; \
- } \
- else \
- len_ = half_; \
- } \
- return first_; \
+ unsigned int len_ = VEC_length (T, vec_);
+ unsigned int half_, middle_;
+ unsigned int first_ = 0;
+ while (len_ > 0)
+ {
+ T middle_elem_;
+ half_ = len_ >> 1;
+ middle_ = first_;
+ middle_ += half_;
+ middle_elem_ = VEC_index_1 (vec_, middle_ VEC_CHECK_PASS);
+ if (lessthan_ (middle_elem_, obj_))
+ {
+ first_ = middle_;
+ ++first_;
+ len_ = len_ - half_ - 1;
+ }
+ else
+ len_ = half_;
+ }
+ return first_;
}
-#define DEF_VEC_ALLOC_FUNC_P(T,A) \
-static inline VEC(T,A) *VEC_OP (T,A,alloc) \
- (int alloc_ MEM_STAT_DECL) \
-{ \
- return (VEC(T,A) *) vec_##A##_p_reserve_exact (NULL, alloc_ \
- PASS_MEM_STAT); \
-}
-
-
-#define DEF_VEC_NONALLOC_FUNCS_P(T,A) \
-static inline void VEC_OP (T,A,free) \
- (VEC(T,A) **vec_) \
-{ \
- if (*vec_) \
- vec_##A##_free (*vec_); \
- *vec_ = NULL; \
-} \
- \
-static inline VEC(T,A) *VEC_OP (T,A,copy) (VEC(T,base) *vec_ MEM_STAT_DECL) \
-{ \
- size_t len_ = vec_ ? vec_->prefix.num : 0; \
- VEC (T,A) *new_vec_ = NULL; \
- \
- if (len_) \
- { \
- new_vec_ = (VEC (T,A) *)(vec_##A##_p_reserve_exact \
- (NULL, len_ PASS_MEM_STAT)); \
- \
- new_vec_->base.prefix.num = len_; \
- memcpy (new_vec_->base.vec, vec_->vec, sizeof (T) * len_); \
- } \
- return new_vec_; \
-} \
- \
-static inline int VEC_OP (T,A,reserve) \
- (VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL) \
-{ \
- int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_ \
- VEC_CHECK_PASS); \
- \
- if (extend) \
- *vec_ = (VEC(T,A) *) vec_##A##_p_reserve (*vec_, alloc_ PASS_MEM_STAT); \
- \
- return extend; \
-} \
- \
-static inline int VEC_OP (T,A,reserve_exact) \
- (VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL) \
-{ \
- int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_ \
- VEC_CHECK_PASS); \
- \
- if (extend) \
- *vec_ = (VEC(T,A) *) vec_##A##_p_reserve_exact (*vec_, alloc_ \
- PASS_MEM_STAT); \
- \
- return extend; \
-} \
- \
-static inline void VEC_OP (T,A,safe_grow) \
- (VEC(T,A) **vec_, int size_ VEC_CHECK_DECL MEM_STAT_DECL) \
-{ \
- VEC_ASSERT (size_ >= 0 \
- && 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_)->prefix.num : 0) \
- VEC_CHECK_PASS PASS_MEM_STAT); \
- VEC_BASE (*vec_)->prefix.num = size_; \
-} \
- \
-static inline void VEC_OP (T,A,safe_grow_cleared) \
- (VEC(T,A) **vec_, int size_ VEC_CHECK_DECL MEM_STAT_DECL) \
-{ \
- int oldsize = VEC_OP(T,base,length) VEC_BASE(*vec_); \
- VEC_OP (T,A,safe_grow) (vec_, size_ VEC_CHECK_PASS PASS_MEM_STAT); \
- memset (&(VEC_OP (T,base,address) VEC_BASE(*vec_))[oldsize], 0, \
- 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) \
-{ \
- VEC_OP (T,A,reserve) (vec_, 1 VEC_CHECK_PASS PASS_MEM_STAT); \
- \
- return VEC_OP (T,base,quick_push) (VEC_BASE(*vec_), obj_ VEC_CHECK_PASS); \
-} \
- \
-static inline T *VEC_OP (T,A,safe_insert) \
- (VEC(T,A) **vec_, unsigned ix_, T obj_ VEC_CHECK_DECL MEM_STAT_DECL) \
-{ \
- VEC_OP (T,A,reserve) (vec_, 1 VEC_CHECK_PASS PASS_MEM_STAT); \
- \
- return VEC_OP (T,base,quick_insert) (VEC_BASE(*vec_), ix_, obj_ \
- VEC_CHECK_PASS); \
-}
-
-/* Vector of object. */
-#define DEF_VEC_O(T) \
-VEC_T_GTY(T,base); \
-VEC_TA(T,base,none); \
-DEF_VEC_FUNC_O(T) \
-struct vec_swallow_trailing_semi
-#define DEF_VEC_ALLOC_O(T,A) \
-VEC_TA(T,base,A); \
-DEF_VEC_ALLOC_FUNC_O(T,A) \
-DEF_VEC_NONALLOC_FUNCS_O(T,A) \
-struct vec_swallow_trailing_semi
-
-/* Vector of atomic object. */
-#define DEF_VEC_A(T) \
-VEC_T_GTY_ATOMIC(T,base); \
-VEC_TA(T,base,none); \
-DEF_VEC_FUNC_O(T) \
-struct vec_swallow_trailing_semi
-#define DEF_VEC_ALLOC_A(T,A) DEF_VEC_ALLOC_O(T,A)
-
-#define DEF_VEC_FUNC_O(T) \
-static inline unsigned VEC_OP (T,base,length) (const VEC(T,base) *vec_) \
-{ \
- 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_->prefix.num, "last", T, base); \
- \
- 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_->prefix.num, "index", T, base); \
- \
- return &vec_->vec[ix_]; \
-} \
- \
-static inline int VEC_OP (T,base,iterate) \
- (VEC(T,base) *vec_, unsigned ix_, T **ptr) \
-{ \
- if (vec_ && ix_ < vec_->prefix.num) \
- { \
- *ptr = &vec_->vec[ix_]; \
- return 1; \
- } \
- else \
- { \
- *ptr = 0; \
- return 0; \
- } \
-} \
- \
-static inline size_t VEC_OP (T,base,embedded_size) \
- (int alloc_) \
-{ \
- return offsetof (VEC(T,base),vec) + alloc_ * sizeof(T); \
-} \
- \
-static inline void VEC_OP (T,base,embedded_init) \
- (VEC(T,base) *vec_, int 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_->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) \
- (VEC(T,base) *vec_, const T *obj_ VEC_CHECK_DECL) \
-{ \
- T *slot_; \
- \
- VEC_ASSERT (vec_->prefix.num < vec_->prefix.alloc, "push", T, base); \
- slot_ = &vec_->vec[vec_->prefix.num++]; \
- if (obj_) \
- *slot_ = *obj_; \
- \
- return slot_; \
-} \
- \
-static inline void VEC_OP (T,base,pop) (VEC(T,base) *vec_ VEC_CHECK_DECL) \
-{ \
- 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_->prefix.num >= size_ : !size_, "truncate", T, base); \
- if (vec_) \
- vec_->prefix.num = size_; \
-} \
- \
-static inline T *VEC_OP (T,base,replace) \
- (VEC(T,base) *vec_, unsigned ix_, const T *obj_ VEC_CHECK_DECL) \
-{ \
- T *slot_; \
- \
- VEC_ASSERT (ix_ < vec_->prefix.num, "replace", T, base); \
- slot_ = &vec_->vec[ix_]; \
- if (obj_) \
- *slot_ = *obj_; \
- \
- return slot_; \
-} \
- \
-static inline T *VEC_OP (T,base,quick_insert) \
- (VEC(T,base) *vec_, unsigned ix_, const T *obj_ VEC_CHECK_DECL) \
-{ \
- T *slot_; \
- \
- 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_->prefix.num++ - ix_) * sizeof (T)); \
- if (obj_) \
- *slot_ = *obj_; \
- \
- return slot_; \
-} \
- \
-static inline void VEC_OP (T,base,ordered_remove) \
- (VEC(T,base) *vec_, unsigned ix_ VEC_CHECK_DECL) \
-{ \
- T *slot_; \
- \
- VEC_ASSERT (ix_ < vec_->prefix.num, "remove", T, base); \
- slot_ = &vec_->vec[ix_]; \
- 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_->prefix.num, "remove", T, base); \
- vec_->vec[ix_] = vec_->vec[--vec_->prefix.num]; \
-} \
- \
-static inline void VEC_OP (T,base,block_remove) \
- (VEC(T,base) *vec_, unsigned ix_, unsigned len_ VEC_CHECK_DECL) \
-{ \
- T *slot_; \
- \
- VEC_ASSERT (ix_ + len_ <= vec_->prefix.num, "block_remove", T, base); \
- slot_ = &vec_->vec[ix_]; \
- vec_->prefix.num -= len_; \
- memmove (slot_, slot_ + len_, (vec_->prefix.num - ix_) * sizeof (T)); \
-} \
- \
-static inline T *VEC_OP (T,base,address) \
- (VEC(T,base) *vec_) \
-{ \
- return vec_ ? vec_->vec : 0; \
-} \
- \
-static inline unsigned VEC_OP (T,base,lower_bound) \
- (VEC(T,base) *vec_, const T *obj_, \
- bool (*lessthan_)(const T *, const T *) VEC_CHECK_DECL) \
-{ \
- unsigned int len_ = VEC_OP (T, base, length) (vec_); \
- unsigned int half_, middle_; \
- unsigned int first_ = 0; \
- while (len_ > 0) \
- { \
- T *middle_elem_; \
- half_ = len_ >> 1; \
- middle_ = first_; \
- middle_ += half_; \
- middle_elem_ = VEC_OP (T,base,index) (vec_, middle_ VEC_CHECK_PASS); \
- if (lessthan_ (middle_elem_, obj_)) \
- { \
- first_ = middle_; \
- ++first_; \
- len_ = len_ - half_ - 1; \
- } \
- else \
- len_ = half_; \
- } \
- return first_; \
-}
-
-#define DEF_VEC_ALLOC_FUNC_O(T,A) \
-static inline VEC(T,A) *VEC_OP (T,A,alloc) \
- (int alloc_ MEM_STAT_DECL) \
-{ \
- return (VEC(T,A) *) vec_##A##_o_reserve_exact (NULL, alloc_, \
- offsetof (VEC(T,A),base.vec), \
- sizeof (T) \
- PASS_MEM_STAT); \
-}
-
-#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_->prefix.num : 0; \
- VEC (T,A) *new_vec_ = NULL; \
- \
- if (len_) \
- { \
- new_vec_ = (VEC (T,A) *)(vec_##A##_o_reserve_exact \
- (NULL, len_, \
- offsetof (VEC(T,A),base.vec), sizeof (T) \
- PASS_MEM_STAT)); \
- \
- new_vec_->base.prefix.num = len_; \
- memcpy (new_vec_->base.vec, vec_->vec, sizeof (T) * len_); \
- } \
- return new_vec_; \
-} \
- \
-static inline void VEC_OP (T,A,free) \
- (VEC(T,A) **vec_) \
-{ \
- if (*vec_) \
- vec_##A##_free (*vec_); \
- *vec_ = NULL; \
-} \
- \
-static inline int VEC_OP (T,A,reserve) \
- (VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL) \
-{ \
- int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_ \
- VEC_CHECK_PASS); \
- \
- if (extend) \
- *vec_ = (VEC(T,A) *) vec_##A##_o_reserve (*vec_, alloc_, \
- offsetof (VEC(T,A),base.vec),\
- sizeof (T) \
- PASS_MEM_STAT); \
- \
- return extend; \
-} \
- \
-static inline int VEC_OP (T,A,reserve_exact) \
- (VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL) \
-{ \
- int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_ \
- VEC_CHECK_PASS); \
- \
- if (extend) \
- *vec_ = (VEC(T,A) *) vec_##A##_o_reserve_exact \
- (*vec_, alloc_, \
- offsetof (VEC(T,A),base.vec), \
- sizeof (T) PASS_MEM_STAT); \
- \
- return extend; \
-} \
- \
-static inline void VEC_OP (T,A,safe_grow) \
- (VEC(T,A) **vec_, int size_ VEC_CHECK_DECL MEM_STAT_DECL) \
-{ \
- VEC_ASSERT (size_ >= 0 \
- && 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_)->prefix.num : 0) \
- VEC_CHECK_PASS PASS_MEM_STAT); \
- VEC_BASE (*vec_)->prefix.num = size_; \
-} \
- \
-static inline void VEC_OP (T,A,safe_grow_cleared) \
- (VEC(T,A) **vec_, int size_ VEC_CHECK_DECL MEM_STAT_DECL) \
-{ \
- int oldsize = VEC_OP(T,base,length) VEC_BASE(*vec_); \
- VEC_OP (T,A,safe_grow) (vec_, size_ VEC_CHECK_PASS PASS_MEM_STAT); \
- memset (&(VEC_OP (T,base,address) VEC_BASE(*vec_))[oldsize], 0, \
- 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) \
-{ \
- VEC_OP (T,A,reserve) (vec_, 1 VEC_CHECK_PASS PASS_MEM_STAT); \
- \
- return VEC_OP (T,base,quick_push) (VEC_BASE(*vec_), obj_ VEC_CHECK_PASS); \
-} \
- \
-static inline T *VEC_OP (T,A,safe_insert) \
- (VEC(T,A) **vec_, unsigned ix_, const T *obj_ \
- VEC_CHECK_DECL MEM_STAT_DECL) \
-{ \
- VEC_OP (T,A,reserve) (vec_, 1 VEC_CHECK_PASS PASS_MEM_STAT); \
- \
- return VEC_OP (T,base,quick_insert) (VEC_BASE(*vec_), ix_, obj_ \
- VEC_CHECK_PASS); \
-}
-
-#define DEF_VEC_ALLOC_FUNC_I(T,A) \
-static inline VEC(T,A) *VEC_OP (T,A,alloc) \
- (int alloc_ MEM_STAT_DECL) \
-{ \
- return (VEC(T,A) *) vec_##A##_o_reserve_exact \
- (NULL, alloc_, offsetof (VEC(T,A),base.vec), \
- sizeof (T) PASS_MEM_STAT); \
-}
-
-#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_->prefix.num : 0; \
- VEC (T,A) *new_vec_ = NULL; \
- \
- if (len_) \
- { \
- new_vec_ = (VEC (T,A) *)(vec_##A##_o_reserve_exact \
- (NULL, len_, \
- offsetof (VEC(T,A),base.vec), sizeof (T) \
- PASS_MEM_STAT)); \
- \
- new_vec_->base.prefix.num = len_; \
- memcpy (new_vec_->base.vec, vec_->vec, sizeof (T) * len_); \
- } \
- return new_vec_; \
-} \
- \
-static inline void VEC_OP (T,A,free) \
- (VEC(T,A) **vec_) \
-{ \
- if (*vec_) \
- vec_##A##_free (*vec_); \
- *vec_ = NULL; \
-} \
- \
-static inline int VEC_OP (T,A,reserve) \
- (VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL) \
-{ \
- int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_ \
- VEC_CHECK_PASS); \
- \
- if (extend) \
- *vec_ = (VEC(T,A) *) vec_##A##_o_reserve (*vec_, alloc_, \
- offsetof (VEC(T,A),base.vec),\
- sizeof (T) \
- PASS_MEM_STAT); \
- \
- return extend; \
-} \
- \
-static inline int VEC_OP (T,A,reserve_exact) \
- (VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL) \
-{ \
- int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_ \
- VEC_CHECK_PASS); \
- \
- if (extend) \
- *vec_ = (VEC(T,A) *) vec_##A##_o_reserve_exact \
- (*vec_, alloc_, offsetof (VEC(T,A),base.vec), \
- sizeof (T) PASS_MEM_STAT); \
- \
- return extend; \
-} \
- \
-static inline void VEC_OP (T,A,safe_grow) \
- (VEC(T,A) **vec_, int size_ VEC_CHECK_DECL MEM_STAT_DECL) \
-{ \
- VEC_ASSERT (size_ >= 0 \
- && 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_)->prefix.num : 0) \
- VEC_CHECK_PASS PASS_MEM_STAT); \
- VEC_BASE (*vec_)->prefix.num = size_; \
-} \
- \
-static inline void VEC_OP (T,A,safe_grow_cleared) \
- (VEC(T,A) **vec_, int size_ VEC_CHECK_DECL MEM_STAT_DECL) \
-{ \
- int oldsize = VEC_OP(T,base,length) VEC_BASE(*vec_); \
- VEC_OP (T,A,safe_grow) (vec_, size_ VEC_CHECK_PASS PASS_MEM_STAT); \
- memset (&(VEC_OP (T,base,address) VEC_BASE(*vec_))[oldsize], 0, \
- 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) \
-{ \
- VEC_OP (T,A,reserve) (vec_, 1 VEC_CHECK_PASS PASS_MEM_STAT); \
- \
- return VEC_OP (T,base,quick_push) (VEC_BASE(*vec_), obj_ VEC_CHECK_PASS); \
-} \
- \
-static inline T *VEC_OP (T,A,safe_insert) \
- (VEC(T,A) **vec_, unsigned ix_, const T obj_ \
- VEC_CHECK_DECL MEM_STAT_DECL) \
-{ \
- VEC_OP (T,A,reserve) (vec_, 1 VEC_CHECK_PASS PASS_MEM_STAT); \
- \
- return VEC_OP (T,base,quick_insert) (VEC_BASE(*vec_), ix_, obj_ \
- VEC_CHECK_PASS); \
+template<typename T>
+static inline unsigned
+VEC_lower_bound_1 (vec_t<T> *vec_, const T *ptr_,
+ bool (*lessthan_)(const T*, const T*) VEC_CHECK_DECL)
+{
+ unsigned int len_ = VEC_length (T, vec_);
+ unsigned int half_, middle_;
+ unsigned int first_ = 0;
+ while (len_ > 0)
+ {
+ T *middle_elem_;
+ half_ = len_ >> 1;
+ middle_ = first_;
+ middle_ += half_;
+ middle_elem_ = &VEC_index_1 (vec_, middle_ VEC_CHECK_PASS);
+ if (lessthan_ (middle_elem_, ptr_))
+ {
+ first_ = middle_;
+ ++first_;
+ len_ = len_ - half_ - 1;
+ }
+ else
+ len_ = half_;
+ }
+ return first_;
}
-/* We support a vector which starts out with space on the stack and
- switches to heap space when forced to reallocate. This works a
- little differently. Instead of DEF_VEC_ALLOC_P(TYPE, heap|gc), use
- DEF_VEC_ALLOC_P_STACK(TYPE). This uses alloca to get the initial
- space; because alloca can not be usefully called in an inline
- function, and because a macro can not define a macro, you must then
- write a #define for each type:
- #define VEC_{TYPE}_stack_alloc(alloc) \
- VEC_stack_alloc({TYPE}, alloc)
+void *vec_heap_o_reserve_1 (void *, int, size_t, size_t, bool MEM_STAT_DECL);
+void *vec_gc_o_reserve_1 (void *, int, size_t, size_t, bool MEM_STAT_DECL);
- This is really a hack and perhaps can be made better. Note that
- this macro will wind up evaluating the ALLOC parameter twice.
+/* Ensure there are at least RESERVE free slots in VEC_, growing
+ exponentially. If RESERVE < 0 grow exactly, else grow
+ exponentially. As a special case, if VEC_ is NULL, and RESERVE is
+ 0, no vector will be created. */
- Only the initial allocation will be made using alloca, so pass a
- reasonable estimate that doesn't use too much stack space; don't
- pass zero. Don't return a VEC(TYPE,stack) vector from the function
- which allocated it. */
-
-extern void *vec_stack_p_reserve (void *, int MEM_STAT_DECL);
-extern void *vec_stack_p_reserve_exact (void *, int MEM_STAT_DECL);
-extern void *vec_stack_p_reserve_exact_1 (int, void *);
-extern void *vec_stack_o_reserve (void *, int, size_t, size_t MEM_STAT_DECL);
-extern void *vec_stack_o_reserve_exact (void *, int, size_t, size_t
- MEM_STAT_DECL);
-extern void vec_stack_free (void *);
-
-/* Unfortunately, we cannot use MEM_STAT_DECL here. */
-#if GATHER_STATISTICS
-#define VEC_stack_alloc(T,alloc,name,line,function) \
- (VEC_OP (T,stack,alloc1) \
- (alloc, XALLOCAVAR (VEC(T,stack), VEC_embedded_size (T, alloc))))
-#else
-#define VEC_stack_alloc(T,alloc) \
- (VEC_OP (T,stack,alloc1) \
- (alloc, XALLOCAVAR (VEC(T,stack), VEC_embedded_size (T, alloc))))
-#endif
-
-#define DEF_VEC_ALLOC_P_STACK(T) \
-VEC_TA(T,base,stack); \
-DEF_VEC_ALLOC_FUNC_P_STACK(T) \
-DEF_VEC_NONALLOC_FUNCS_P(T,stack) \
-struct vec_swallow_trailing_semi
-
-#define DEF_VEC_ALLOC_FUNC_P_STACK(T) \
-static inline VEC(T,stack) *VEC_OP (T,stack,alloc1) \
- (int alloc_, VEC(T,stack)* space) \
-{ \
- return (VEC(T,stack) *) vec_stack_p_reserve_exact_1 (alloc_, space); \
+template<typename T, enum vec_allocation_t A>
+vec_t<T> *
+vec_reserve (vec_t<T> *vec_, int reserve MEM_STAT_DECL)
+{
+ if (A == gc)
+ return (vec_t<T> *) vec_gc_o_reserve_1 (vec_, reserve,
+ offsetof (vec_t<T>, vec),
+ sizeof (T), false
+ PASS_MEM_STAT);
+ else if (A == heap)
+ return (vec_t<T> *) vec_heap_o_reserve_1 (vec_, reserve,
+ offsetof (vec_t<T>, vec),
+ sizeof (T), false
+ PASS_MEM_STAT);
+ else
+ {
+ /* Only allow stack vectors when re-growing them. The initial
+ allocation of stack vectors must be done with the
+ VEC_stack_alloc macro, because it uses alloca() for the
+ allocation. */
+ if (vec_ == NULL)
+ {
+ fprintf (stderr, "Stack vectors must be initially allocated "
+ "with VEC_stack_alloc.\n");
+ gcc_unreachable ();
+ }
+ return (vec_t<T> *) vec_stack_o_reserve (vec_, reserve,
+ offsetof (vec_t<T>, vec),
+ sizeof (T) PASS_MEM_STAT);
+ }
}
-#define DEF_VEC_ALLOC_O_STACK(T) \
-VEC_TA(T,base,stack); \
-DEF_VEC_ALLOC_FUNC_O_STACK(T) \
-DEF_VEC_NONALLOC_FUNCS_O(T,stack) \
-struct vec_swallow_trailing_semi
-#define DEF_VEC_ALLOC_FUNC_O_STACK(T) \
-static inline VEC(T,stack) *VEC_OP (T,stack,alloc1) \
- (int alloc_, VEC(T,stack)* space) \
-{ \
- return (VEC(T,stack) *) vec_stack_p_reserve_exact_1 (alloc_, space); \
-}
-
-#define DEF_VEC_ALLOC_I_STACK(T) \
-VEC_TA(T,base,stack); \
-DEF_VEC_ALLOC_FUNC_I_STACK(T) \
-DEF_VEC_NONALLOC_FUNCS_I(T,stack) \
-struct vec_swallow_trailing_semi
+/* Ensure there are at least RESERVE free slots in VEC_, growing
+ exactly. If RESERVE < 0 grow exactly, else grow exponentially. As
+ a special case, if VEC_ is NULL, and RESERVE is 0, no vector will be
+ created. */
-#define DEF_VEC_ALLOC_FUNC_I_STACK(T) \
-static inline VEC(T,stack) *VEC_OP (T,stack,alloc1) \
- (int alloc_, VEC(T,stack)* space) \
-{ \
- return (VEC(T,stack) *) vec_stack_p_reserve_exact_1 (alloc_, space); \
+template<typename T, enum vec_allocation_t A>
+vec_t<T> *
+vec_reserve_exact (vec_t<T> *vec_, int reserve MEM_STAT_DECL)
+{
+ if (A == gc)
+ return (vec_t<T> *) vec_gc_o_reserve_1 (vec_, reserve,
+ sizeof (struct vec_prefix),
+ sizeof (T), true
+ PASS_MEM_STAT);
+ else if (A == heap)
+ return (vec_t<T> *) vec_heap_o_reserve_1 (vec_, reserve,
+ sizeof (struct vec_prefix),
+ sizeof (T), true
+ PASS_MEM_STAT);
+ else if (A == stack)
+ {
+ /* Only allow stack vectors when re-growing them. The initial
+ allocation of stack vectors must be done with VEC_alloc,
+ because it uses alloca() for the allocation. */
+ if (vec_ == NULL)
+ {
+ fprintf (stderr, "Stack vectors must be initially allocated "
+ "with VEC_stack_alloc.\n");
+ gcc_unreachable ();
+ }
+ return (vec_t<T> *) vec_stack_o_reserve_exact (vec_, reserve,
+ sizeof (struct vec_prefix),
+ sizeof (T)
+ PASS_MEM_STAT);
+ }
}
#endif /* GCC_VEC_H */