You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
#ifndef GCC_VEC_H
#define GCC_VEC_H
least as many elements as you ask for, it will exponentially
increase if there are too few spare slots. If you want reserve a
specific number of slots, but do not want the exponential increase
- (for instance, you know this is the last allocation), use a
- negative number for reservation. You can also create a vector of a
+ (for instance, you know this is the last allocation), use the
+ reserve_exact operation. You can also create a vector of a
specific size from the get go.
You should prefer the push and pop operations, as they append and
#define VEC_length(T,V) (VEC_OP(T,base,length)(VEC_BASE(V)))
+
+/* Check if vector is empty
+ int VEC_T_empty(const VEC(T) *v);
+
+ Return nonzero if V is an empty vector (or V is NULL), zero otherwise. */
+
+#define VEC_empty(T,V) (VEC_length (T,V) == 0)
+
+
/* Get the final element of the vector.
T VEC_T_last(VEC(T) *v); // Integer
T VEC_T_last(VEC(T) *v); // Pointer
#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) *);
+
+ 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))
+
/* Determine if a vector has additional capacity.
int VEC_T_space (VEC(T) *v,int reserve)
/* Reserve space.
int VEC_T_A_reserve(VEC(T,A) *&v, int reserve);
- Ensure that V has at least abs(RESERVE) slots available. The
- signedness of RESERVE determines the reallocation behavior. A
- negative value will not create additional headroom beyond that
- requested. A positive value will create additional headroom. Note
- this can cause V to be reallocated. Returns nonzero iff
- reallocation actually occurred. */
+ Ensure that V has at least RESERVE slots available. This will
+ create additional headroom. Note this can cause V to be
+ reallocated. Returns nonzero iff reallocation actually
+ occurred. */
#define VEC_reserve(T,A,V,R) \
(VEC_OP(T,A,reserve)(&(V),R VEC_CHECK_INFO MEM_STAT_INFO))
+/* Reserve space exactly.
+ int VEC_T_A_reserve_exact(VEC(T,A) *&v, int reserve);
+
+ Ensure that V has at least RESERVE slots available. This will not
+ create additional headroom. Note this can cause V to be
+ reallocated. Returns nonzero iff reallocation actually
+ occurred. */
+
+#define VEC_reserve_exact(T,A,V,R) \
+ (VEC_OP(T,A,reserve_exact)(&(V),R 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
uninitialized. */
#define VEC_safe_grow(T,A,V,I) \
- (VEC_OP(T,A,safe_grow)(&(V),I VEC_CHECK_INFO))
+ (VEC_OP(T,A,safe_grow)(&(V),I VEC_CHECK_INFO MEM_STAT_INFO))
+
+/* Grow to a specific length.
+ void VEC_T_A_safe_grow_cleared (VEC(T,A) *&v, int len);
+
+ Grow the vector to a specific length. The LEN must be as
+ 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))
/* Replace element
T VEC_T_replace (VEC(T) *v, unsigned ix, T val); // Integer
#define VEC_unordered_remove(T,V,I) \
(VEC_OP(T,base,unordered_remove)(VEC_BASE(V),I VEC_CHECK_INFO))
+/* Remove a block of elements
+ 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. */
+
+#define VEC_block_remove(T,V,I,L) \
+ (VEC_OP(T,base,block_remove)(VEC_BASE(V),I,L VEC_CHECK_INFO))
+
/* Get the address of the array of elements
T *VEC_T_address (VEC(T) v)
#define VEC_lower_bound(T,V,O,LT) \
(VEC_OP(T,base,lower_bound)(VEC_BASE(V),O,LT VEC_CHECK_INFO))
-#if !IN_GENGTYPE
/* 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);
#define vec_heap_free(V) free (V)
#if ENABLE_CHECKING
#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. */
+
#define VEC(T,A) VEC_##T##_##A
#define VEC_OP(T,A,OP) VEC_##T##_##A##_##OP
-#else /* IN_GENGTYPE */
-#define VEC(T,A) VEC_ T _ A
-#define VEC_STRINGIFY(X) VEC_STRINGIFY_(X)
-#define VEC_STRINGIFY_(X) #X
-#undef GTY
-#endif /* IN_GENGTYPE */
/* Base of vector type, not user visible. */
#define VEC_T(T,B) \
#define VEC_BASE(P) ((P) ? &(P)->base : 0)
/* Vector of integer-like object. */
-#if IN_GENGTYPE
-{"DEF_VEC_I", VEC_STRINGIFY (VEC_T(#0,#1)) ";", "none"},
-{"DEF_VEC_ALLOC_I", VEC_STRINGIFY (VEC_TA (#0,#1,#2,#3)) ";", NULL},
-#else
#define DEF_VEC_I(T) \
static inline void VEC_OP (T,must_be,integral_type) (void) \
{ \
struct vec_swallow_trailing_semi
#define DEF_VEC_ALLOC_I(T,A) \
VEC_TA_GTY(T,base,A,); \
-DEF_VEC_ALLOC_FUNC_P(T,A) \
+DEF_VEC_ALLOC_FUNC_I(T,A) \
struct vec_swallow_trailing_semi
-#endif
/* Vector of pointer to object. */
-#if IN_GENGTYPE
-{"DEF_VEC_P", VEC_STRINGIFY (VEC_T_GTY(#0,#1)) ";", "none"},
-{"DEF_VEC_ALLOC_P", VEC_STRINGIFY (VEC_TA_GTY (#0,#1,#2,#3)) ";", NULL},
-#else
#define DEF_VEC_P(T) \
static inline void VEC_OP (T,must_be,pointer_type) (void) \
{ \
VEC_TA_GTY(T,base,A,); \
DEF_VEC_ALLOC_FUNC_P(T,A) \
struct vec_swallow_trailing_semi
-#endif
#define DEF_VEC_FUNC_P(T) \
static inline unsigned VEC_OP (T,base,length) (const VEC(T,base) *vec_) \
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_->num, "block_remove", T, base); \
+ slot_ = &vec_->vec[ix_]; \
+ vec_->num -= len_; \
+ memmove (slot_, slot_ + len_, (vec_->num - ix_) * sizeof (T)); \
+} \
+ \
static inline T *VEC_OP (T,base,address) \
(VEC(T,base) *vec_) \
{ \
static inline VEC(T,A) *VEC_OP (T,A,alloc) \
(int alloc_ MEM_STAT_DECL) \
{ \
- /* We must request exact size allocation, hence the negation. */ \
- return (VEC(T,A) *) vec_##A##_p_reserve (NULL, -alloc_ PASS_MEM_STAT); \
+ return (VEC(T,A) *) vec_##A##_p_reserve_exact (NULL, alloc_ \
+ PASS_MEM_STAT); \
} \
\
static inline void VEC_OP (T,A,free) \
*vec_ = NULL; \
} \
\
+static inline VEC(T,A) *VEC_OP (T,A,copy) (VEC(T,base) *vec_ MEM_STAT_DECL) \
+{ \
+ size_t len_ = vec_ ? vec_->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.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_ < 0 ? -alloc_ : alloc_ \
+ int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_ \
VEC_CHECK_PASS); \
\
if (extend) \
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) (vec_, (int)(*vec_ ? VEC_BASE(*vec_)->num : 0) - size_ \
- VEC_CHECK_PASS PASS_MEM_STAT); \
+ VEC_OP (T,A,reserve_exact) (vec_, \
+ size_ - (int)(*vec_ ? VEC_BASE(*vec_)->num : 0) \
+ VEC_CHECK_PASS PASS_MEM_STAT); \
VEC_BASE (*vec_)->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 T *VEC_OP (T,A,safe_push) \
(VEC(T,A) **vec_, T obj_ VEC_CHECK_DECL MEM_STAT_DECL) \
{ \
}
/* Vector of object. */
-#if IN_GENGTYPE
-{"DEF_VEC_O", VEC_STRINGIFY (VEC_T_GTY(#0,#1)) ";", "none"},
-{"DEF_VEC_ALLOC_O", VEC_STRINGIFY (VEC_TA_GTY(#0,#1,#2,#3)) ";", NULL},
-#else
#define DEF_VEC_O(T) \
VEC_T_GTY(T,base); \
VEC_TA_GTY(T,base,none,); \
VEC_TA_GTY(T,base,A,); \
DEF_VEC_ALLOC_FUNC_O(T,A) \
struct vec_swallow_trailing_semi
-#endif
#define DEF_VEC_FUNC_O(T) \
static inline unsigned VEC_OP (T,base,length) (const VEC(T,base) *vec_) \
vec_->vec[ix_] = vec_->vec[--vec_->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_->num, "block_remove", T, base); \
+ slot_ = &vec_->vec[ix_]; \
+ vec_->num -= len_; \
+ memmove (slot_, slot_ + len_, (vec_->num - ix_) * sizeof (T)); \
+} \
+ \
static inline T *VEC_OP (T,base,address) \
(VEC(T,base) *vec_) \
{ \
static inline VEC(T,A) *VEC_OP (T,A,alloc) \
(int alloc_ MEM_STAT_DECL) \
{ \
- /* We must request exact size allocation, hence the negation. */ \
- return (VEC(T,A) *) vec_##A##_o_reserve (NULL, -alloc_, \
- offsetof (VEC(T,A),base.vec), \
- sizeof (T) \
- PASS_MEM_STAT); \
+ return (VEC(T,A) *) vec_##A##_o_reserve_exact (NULL, alloc_, \
+ offsetof (VEC(T,A),base.vec), \
+ sizeof (T) \
+ PASS_MEM_STAT); \
+} \
+ \
+static inline VEC(T,A) *VEC_OP (T,A,copy) (VEC(T,base) *vec_ MEM_STAT_DECL) \
+{ \
+ size_t len_ = vec_ ? vec_->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.num = len_; \
+ memcpy (new_vec_->base.vec, vec_->vec, sizeof (T) * len_); \
+ } \
+ return new_vec_; \
} \
\
static inline void VEC_OP (T,A,free) \
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_ < 0 ? -alloc_ : alloc_ \
+ int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_ \
VEC_CHECK_PASS); \
\
if (extend) \
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) (vec_, (int)(*vec_ ? VEC_BASE(*vec_)->num : 0) - size_ \
- VEC_CHECK_PASS PASS_MEM_STAT); \
- VEC_BASE (*vec_)->num = size_; \
+ VEC_OP (T,A,reserve_exact) (vec_, \
+ size_ - (int)(*vec_ ? VEC_BASE(*vec_)->num : 0) \
+ VEC_CHECK_PASS PASS_MEM_STAT); \
VEC_BASE (*vec_)->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 T *VEC_OP (T,A,safe_push) \
(VEC(T,A) **vec_, const T *obj_ VEC_CHECK_DECL MEM_STAT_DECL) \
{ \
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); \
+} \
+ \
+static inline VEC(T,A) *VEC_OP (T,A,copy) (VEC(T,base) *vec_ MEM_STAT_DECL) \
+{ \
+ size_t len_ = vec_ ? vec_->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.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_)->num : 0) \
+ VEC_CHECK_PASS PASS_MEM_STAT); \
+ VEC_BASE (*vec_)->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 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); \
+}
+
#endif /* GCC_VEC_H */