Mark as release
[official-gcc.git] / gcc / vec.h
blob456de9c4fe7e5ba86cbbe36d52a539bcdacd3d94
1 /* Vector API for GNU compiler.
2 Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
3 Contributed by Nathan Sidwell <nathan@codesourcery.com>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #ifndef GCC_VEC_H
22 #define GCC_VEC_H
24 /* The macros here implement a set of templated vector types and
25 associated interfaces. These templates are implemented with
26 macros, as we're not in C++ land. The interface functions are
27 typesafe and use static inline functions, sometimes backed by
28 out-of-line generic functions. The vectors are designed to
29 interoperate with the GTY machinery.
31 Because of the different behavior of structure objects, scalar
32 objects and of pointers, there are three flavors, one for each of
33 these variants. Both the structure object and pointer variants
34 pass pointers to objects around -- in the former case the pointers
35 are stored into the vector and in the latter case the pointers are
36 dereferenced and the objects copied into the vector. The scalar
37 object variant is suitable for int-like objects, and the vector
38 elements are returned by value.
40 There are both 'index' and 'iterate' accessors. The iterator
41 returns a boolean iteration condition and updates the iteration
42 variable passed by reference. Because the iterator will be
43 inlined, the address-of can be optimized away.
45 The vectors are implemented using the trailing array idiom, thus
46 they are not resizeable without changing the address of the vector
47 object itself. This means you cannot have variables or fields of
48 vector type -- always use a pointer to a vector. The one exception
49 is the final field of a structure, which could be a vector type.
50 You will have to use the embedded_size & embedded_init calls to
51 create such objects, and they will probably not be resizeable (so
52 don't use the 'safe' allocation variants). The trailing array
53 idiom is used (rather than a pointer to an array of data), because,
54 if we allow NULL to also represent an empty vector, empty vectors
55 occupy minimal space in the structure containing them.
57 Each operation that increases the number of active elements is
58 available in 'quick' and 'safe' variants. The former presumes that
59 there is sufficient allocated space for the operation to succeed
60 (it dies if there is not). The latter will reallocate the
61 vector, if needed. Reallocation causes an exponential increase in
62 vector size. If you know you will be adding N elements, it would
63 be more efficient to use the reserve operation before adding the
64 elements with the 'quick' operation. This will ensure there are at
65 least as many elements as you ask for, it will exponentially
66 increase if there are too few spare slots. If you want reserve a
67 specific number of slots, but do not want the exponential increase
68 (for instance, you know this is the last allocation), use the
69 reserve_exact operation. You can also create a vector of a
70 specific size from the get go.
72 You should prefer the push and pop operations, as they append and
73 remove from the end of the vector. If you need to remove several
74 items in one go, use the truncate operation. The insert and remove
75 operations allow you to change elements in the middle of the
76 vector. There are two remove operations, one which preserves the
77 element ordering 'ordered_remove', and one which does not
78 'unordered_remove'. The latter function copies the end element
79 into the removed slot, rather than invoke a memmove operation. The
80 'lower_bound' function will determine where to place an item in the
81 array using insert that will maintain sorted order.
83 When a vector type is defined, first a non-memory managed version
84 is created. You can then define either or both garbage collected
85 and heap allocated versions. The allocation mechanism is specified
86 when the type is defined, and is therefore part of the type. If
87 you need both gc'd and heap allocated versions, you still must have
88 *exactly* one definition of the common non-memory managed base vector.
90 If you need to directly manipulate a vector, then the 'address'
91 accessor will return the address of the start of the vector. Also
92 the 'space' predicate will tell you whether there is spare capacity
93 in the vector. You will not normally need to use these two functions.
95 Vector types are defined using a DEF_VEC_{O,P,I}(TYPEDEF) macro, to
96 get the non-memory allocation version, and then a
97 DEF_VEC_ALLOC_{O,P,I}(TYPEDEF,ALLOC) macro to get memory managed
98 vectors. Variables of vector type are declared using a
99 VEC(TYPEDEF,ALLOC) macro. The ALLOC argument specifies the
100 allocation strategy, and can be either 'gc' or 'heap' for garbage
101 collected and heap allocated respectively. It can be 'none' to get
102 a vector that must be explicitly allocated (for instance as a
103 trailing array of another structure). The characters O, P and I
104 indicate whether TYPEDEF is a pointer (P), object (O) or integral
105 (I) type. Be careful to pick the correct one, as you'll get an
106 awkward and inefficient API if you use the wrong one. There is a
107 check, which results in a compile-time warning, for the P and I
108 versions, but there is no check for the O versions, as that is not
109 possible in plain C. Due to the way GTY works, you must annotate
110 any structures you wish to insert or reference from a vector with a
111 GTY(()) tag. You need to do this even if you never declare the GC
112 allocated variants.
114 An example of their use would be,
116 DEF_VEC_P(tree); // non-managed tree vector.
117 DEF_VEC_ALLOC_P(tree,gc); // gc'd vector of tree pointers. This must
118 // appear at file scope.
120 struct my_struct {
121 VEC(tree,gc) *v; // A (pointer to) a vector of tree pointers.
124 struct my_struct *s;
126 if (VEC_length(tree,s->v)) { we have some contents }
127 VEC_safe_push(tree,gc,s->v,decl); // append some decl onto the end
128 for (ix = 0; VEC_iterate(tree,s->v,ix,elt); ix++)
129 { do something with elt }
133 /* Macros to invoke API calls. A single macro works for both pointer
134 and object vectors, but the argument and return types might well be
135 different. In each macro, T is the typedef of the vector elements,
136 and A is the allocation strategy. The allocation strategy is only
137 present when it is required. Some of these macros pass the vector,
138 V, by reference (by taking its address), this is noted in the
139 descriptions. */
141 /* Length of vector
142 unsigned VEC_T_length(const VEC(T) *v);
144 Return the number of active elements in V. V can be NULL, in which
145 case zero is returned. */
147 #define VEC_length(T,V) (VEC_OP(T,base,length)(VEC_BASE(V)))
150 /* Check if vector is empty
151 int VEC_T_empty(const VEC(T) *v);
153 Return nonzero if V is an empty vector (or V is NULL), zero otherwise. */
155 #define VEC_empty(T,V) (VEC_length (T,V) == 0)
158 /* Get the final element of the vector.
159 T VEC_T_last(VEC(T) *v); // Integer
160 T VEC_T_last(VEC(T) *v); // Pointer
161 T *VEC_T_last(VEC(T) *v); // Object
163 Return the final element. V must not be empty. */
165 #define VEC_last(T,V) (VEC_OP(T,base,last)(VEC_BASE(V) VEC_CHECK_INFO))
167 /* Index into vector
168 T VEC_T_index(VEC(T) *v, unsigned ix); // Integer
169 T VEC_T_index(VEC(T) *v, unsigned ix); // Pointer
170 T *VEC_T_index(VEC(T) *v, unsigned ix); // Object
172 Return the IX'th element. If IX must be in the domain of V. */
174 #define VEC_index(T,V,I) (VEC_OP(T,base,index)(VEC_BASE(V),I VEC_CHECK_INFO))
176 /* Iterate over vector
177 int VEC_T_iterate(VEC(T) *v, unsigned ix, T &ptr); // Integer
178 int VEC_T_iterate(VEC(T) *v, unsigned ix, T &ptr); // Pointer
179 int VEC_T_iterate(VEC(T) *v, unsigned ix, T *&ptr); // Object
181 Return iteration condition and update PTR to point to the IX'th
182 element. At the end of iteration, sets PTR to NULL. Use this to
183 iterate over the elements of a vector as follows,
185 for (ix = 0; VEC_iterate(T,v,ix,ptr); ix++)
186 continue; */
188 #define VEC_iterate(T,V,I,P) (VEC_OP(T,base,iterate)(VEC_BASE(V),I,&(P)))
190 /* Allocate new vector.
191 VEC(T,A) *VEC_T_A_alloc(int reserve);
193 Allocate a new vector with space for RESERVE objects. If RESERVE
194 is zero, NO vector is created. */
196 #define VEC_alloc(T,A,N) (VEC_OP(T,A,alloc)(N MEM_STAT_INFO))
198 /* Free a vector.
199 void VEC_T_A_free(VEC(T,A) *&);
201 Free a vector and set it to NULL. */
203 #define VEC_free(T,A,V) (VEC_OP(T,A,free)(&V))
205 /* Use these to determine the required size and initialization of a
206 vector embedded within another structure (as the final member).
208 size_t VEC_T_embedded_size(int reserve);
209 void VEC_T_embedded_init(VEC(T) *v, int reserve);
211 These allow the caller to perform the memory allocation. */
213 #define VEC_embedded_size(T,N) (VEC_OP(T,base,embedded_size)(N))
214 #define VEC_embedded_init(T,O,N) (VEC_OP(T,base,embedded_init)(VEC_BASE(O),N))
216 /* Copy a vector.
217 VEC(T,A) *VEC_T_A_copy(VEC(T) *);
219 Copy the live elements of a vector into a new vector. The new and
220 old vectors need not be allocated by the same mechanism. */
222 #define VEC_copy(T,A,V) (VEC_OP(T,A,copy)(VEC_BASE(V) MEM_STAT_INFO))
224 /* Determine if a vector has additional capacity.
226 int VEC_T_space (VEC(T) *v,int reserve)
228 If V has space for RESERVE additional entries, return nonzero. You
229 usually only need to use this if you are doing your own vector
230 reallocation, for instance on an embedded vector. This returns
231 nonzero in exactly the same circumstances that VEC_T_reserve
232 will. */
234 #define VEC_space(T,V,R) \
235 (VEC_OP(T,base,space)(VEC_BASE(V),R VEC_CHECK_INFO))
237 /* Reserve space.
238 int VEC_T_A_reserve(VEC(T,A) *&v, int reserve);
240 Ensure that V has at least RESERVE slots available. This will
241 create additional headroom. Note this can cause V to be
242 reallocated. Returns nonzero iff reallocation actually
243 occurred. */
245 #define VEC_reserve(T,A,V,R) \
246 (VEC_OP(T,A,reserve)(&(V),R VEC_CHECK_INFO MEM_STAT_INFO))
248 /* Reserve space exactly.
249 int VEC_T_A_reserve_exact(VEC(T,A) *&v, int reserve);
251 Ensure that V has at least RESERVE slots available. This will not
252 create additional headroom. Note this can cause V to be
253 reallocated. Returns nonzero iff reallocation actually
254 occurred. */
256 #define VEC_reserve_exact(T,A,V,R) \
257 (VEC_OP(T,A,reserve_exact)(&(V),R VEC_CHECK_INFO MEM_STAT_INFO))
259 /* Push object with no reallocation
260 T *VEC_T_quick_push (VEC(T) *v, T obj); // Integer
261 T *VEC_T_quick_push (VEC(T) *v, T obj); // Pointer
262 T *VEC_T_quick_push (VEC(T) *v, T *obj); // Object
264 Push a new element onto the end, returns a pointer to the slot
265 filled in. For object vectors, the new value can be NULL, in which
266 case NO initialization is performed. There must
267 be sufficient space in the vector. */
269 #define VEC_quick_push(T,V,O) \
270 (VEC_OP(T,base,quick_push)(VEC_BASE(V),O VEC_CHECK_INFO))
272 /* Push object with reallocation
273 T *VEC_T_A_safe_push (VEC(T,A) *&v, T obj); // Integer
274 T *VEC_T_A_safe_push (VEC(T,A) *&v, T obj); // Pointer
275 T *VEC_T_A_safe_push (VEC(T,A) *&v, T *obj); // Object
277 Push a new element onto the end, returns a pointer to the slot
278 filled in. For object vectors, the new value can be NULL, in which
279 case NO initialization is performed. Reallocates V, if needed. */
281 #define VEC_safe_push(T,A,V,O) \
282 (VEC_OP(T,A,safe_push)(&(V),O VEC_CHECK_INFO MEM_STAT_INFO))
284 /* Pop element off end
285 T VEC_T_pop (VEC(T) *v); // Integer
286 T VEC_T_pop (VEC(T) *v); // Pointer
287 void VEC_T_pop (VEC(T) *v); // Object
289 Pop the last element off the end. Returns the element popped, for
290 pointer vectors. */
292 #define VEC_pop(T,V) (VEC_OP(T,base,pop)(VEC_BASE(V) VEC_CHECK_INFO))
294 /* Truncate to specific length
295 void VEC_T_truncate (VEC(T) *v, unsigned len);
297 Set the length as specified. The new length must be less than or
298 equal to the current length. This is an O(1) operation. */
300 #define VEC_truncate(T,V,I) \
301 (VEC_OP(T,base,truncate)(VEC_BASE(V),I VEC_CHECK_INFO))
303 /* Grow to a specific length.
304 void VEC_T_A_safe_grow (VEC(T,A) *&v, int len);
306 Grow the vector to a specific length. The LEN must be as
307 long or longer than the current length. The new elements are
308 uninitialized. */
310 #define VEC_safe_grow(T,A,V,I) \
311 (VEC_OP(T,A,safe_grow)(&(V),I VEC_CHECK_INFO MEM_STAT_INFO))
313 /* Replace element
314 T VEC_T_replace (VEC(T) *v, unsigned ix, T val); // Integer
315 T VEC_T_replace (VEC(T) *v, unsigned ix, T val); // Pointer
316 T *VEC_T_replace (VEC(T) *v, unsigned ix, T *val); // Object
318 Replace the IXth element of V with a new value, VAL. For pointer
319 vectors returns the original value. For object vectors returns a
320 pointer to the new value. For object vectors the new value can be
321 NULL, in which case no overwriting of the slot is actually
322 performed. */
324 #define VEC_replace(T,V,I,O) \
325 (VEC_OP(T,base,replace)(VEC_BASE(V),I,O VEC_CHECK_INFO))
327 /* Insert object with no reallocation
328 T *VEC_T_quick_insert (VEC(T) *v, unsigned ix, T val); // Integer
329 T *VEC_T_quick_insert (VEC(T) *v, unsigned ix, T val); // Pointer
330 T *VEC_T_quick_insert (VEC(T) *v, unsigned ix, T *val); // Object
332 Insert an element, VAL, at the IXth position of V. Return a pointer
333 to the slot created. For vectors of object, the new value can be
334 NULL, in which case no initialization of the inserted slot takes
335 place. There must be sufficient space. */
337 #define VEC_quick_insert(T,V,I,O) \
338 (VEC_OP(T,base,quick_insert)(VEC_BASE(V),I,O VEC_CHECK_INFO))
340 /* Insert object with reallocation
341 T *VEC_T_A_safe_insert (VEC(T,A) *&v, unsigned ix, T val); // Integer
342 T *VEC_T_A_safe_insert (VEC(T,A) *&v, unsigned ix, T val); // Pointer
343 T *VEC_T_A_safe_insert (VEC(T,A) *&v, unsigned ix, T *val); // Object
345 Insert an element, VAL, at the IXth position of V. Return a pointer
346 to the slot created. For vectors of object, the new value can be
347 NULL, in which case no initialization of the inserted slot takes
348 place. Reallocate V, if necessary. */
350 #define VEC_safe_insert(T,A,V,I,O) \
351 (VEC_OP(T,A,safe_insert)(&(V),I,O VEC_CHECK_INFO MEM_STAT_INFO))
353 /* Remove element retaining order
354 T VEC_T_ordered_remove (VEC(T) *v, unsigned ix); // Integer
355 T VEC_T_ordered_remove (VEC(T) *v, unsigned ix); // Pointer
356 void VEC_T_ordered_remove (VEC(T) *v, unsigned ix); // Object
358 Remove an element from the IXth position of V. Ordering of
359 remaining elements is preserved. For pointer vectors returns the
360 removed object. This is an O(N) operation due to a memmove. */
362 #define VEC_ordered_remove(T,V,I) \
363 (VEC_OP(T,base,ordered_remove)(VEC_BASE(V),I VEC_CHECK_INFO))
365 /* Remove element destroying order
366 T VEC_T_unordered_remove (VEC(T) *v, unsigned ix); // Integer
367 T VEC_T_unordered_remove (VEC(T) *v, unsigned ix); // Pointer
368 void VEC_T_unordered_remove (VEC(T) *v, unsigned ix); // Object
370 Remove an element from the IXth position of V. Ordering of
371 remaining elements is destroyed. For pointer vectors returns the
372 removed object. This is an O(1) operation. */
374 #define VEC_unordered_remove(T,V,I) \
375 (VEC_OP(T,base,unordered_remove)(VEC_BASE(V),I VEC_CHECK_INFO))
377 /* Remove a block of elements
378 void VEC_T_block_remove (VEC(T) *v, unsigned ix, unsigned len);
380 Remove LEN elements starting at the IXth. Ordering is retained.
381 This is an O(1) operation. */
383 #define VEC_block_remove(T,V,I,L) \
384 (VEC_OP(T,base,block_remove)(VEC_BASE(V),I,L VEC_CHECK_INFO))
386 /* Get the address of the array of elements
387 T *VEC_T_address (VEC(T) v)
389 If you need to directly manipulate the array (for instance, you
390 want to feed it to qsort), use this accessor. */
392 #define VEC_address(T,V) (VEC_OP(T,base,address)(VEC_BASE(V)))
394 /* Find the first index in the vector not less than the object.
395 unsigned VEC_T_lower_bound (VEC(T) *v, const T val,
396 bool (*lessthan) (const T, const T)); // Integer
397 unsigned VEC_T_lower_bound (VEC(T) *v, const T val,
398 bool (*lessthan) (const T, const T)); // Pointer
399 unsigned VEC_T_lower_bound (VEC(T) *v, const T *val,
400 bool (*lessthan) (const T*, const T*)); // Object
402 Find the first position in which VAL could be inserted without
403 changing the ordering of V. LESSTHAN is a function that returns
404 true if the first argument is strictly less than the second. */
406 #define VEC_lower_bound(T,V,O,LT) \
407 (VEC_OP(T,base,lower_bound)(VEC_BASE(V),O,LT VEC_CHECK_INFO))
409 #if !IN_GENGTYPE
410 /* Reallocate an array of elements with prefix. */
411 extern void *vec_gc_p_reserve (void *, int MEM_STAT_DECL);
412 extern void *vec_gc_p_reserve_exact (void *, int MEM_STAT_DECL);
413 extern void *vec_gc_o_reserve (void *, int, size_t, size_t MEM_STAT_DECL);
414 extern void *vec_gc_o_reserve_exact (void *, int, size_t, size_t
415 MEM_STAT_DECL);
416 extern void ggc_free (void *);
417 #define vec_gc_free(V) ggc_free (V)
418 extern void *vec_heap_p_reserve (void *, int MEM_STAT_DECL);
419 extern void *vec_heap_p_reserve_exact (void *, int MEM_STAT_DECL);
420 extern void *vec_heap_o_reserve (void *, int, size_t, size_t MEM_STAT_DECL);
421 extern void *vec_heap_o_reserve_exact (void *, int, size_t, size_t
422 MEM_STAT_DECL);
423 #define vec_heap_free(V) free (V)
425 #if ENABLE_CHECKING
426 #define VEC_CHECK_INFO ,__FILE__,__LINE__,__FUNCTION__
427 #define VEC_CHECK_DECL ,const char *file_,unsigned line_,const char *function_
428 #define VEC_CHECK_PASS ,file_,line_,function_
430 #define VEC_ASSERT(EXPR,OP,T,A) \
431 (void)((EXPR) ? 0 : (VEC_ASSERT_FAIL(OP,VEC(T,A)), 0))
433 extern void vec_assert_fail (const char *, const char * VEC_CHECK_DECL)
434 ATTRIBUTE_NORETURN;
435 #define VEC_ASSERT_FAIL(OP,VEC) vec_assert_fail (OP,#VEC VEC_CHECK_PASS)
436 #else
437 #define VEC_CHECK_INFO
438 #define VEC_CHECK_DECL
439 #define VEC_CHECK_PASS
440 #define VEC_ASSERT(EXPR,OP,T,A) (void)(EXPR)
441 #endif
443 #define VEC(T,A) VEC_##T##_##A
444 #define VEC_OP(T,A,OP) VEC_##T##_##A##_##OP
445 #else /* IN_GENGTYPE */
446 #define VEC(T,A) VEC_ T _ A
447 #define VEC_STRINGIFY(X) VEC_STRINGIFY_(X)
448 #define VEC_STRINGIFY_(X) #X
449 #undef GTY
450 #endif /* IN_GENGTYPE */
452 /* Base of vector type, not user visible. */
453 #define VEC_T(T,B) \
454 typedef struct VEC(T,B) \
456 unsigned num; \
457 unsigned alloc; \
458 T vec[1]; \
459 } VEC(T,B)
461 #define VEC_T_GTY(T,B) \
462 typedef struct VEC(T,B) GTY(()) \
464 unsigned num; \
465 unsigned alloc; \
466 T GTY ((length ("%h.num"))) vec[1]; \
467 } VEC(T,B)
469 /* Derived vector type, user visible. */
470 #define VEC_TA_GTY(T,B,A,GTY) \
471 typedef struct VEC(T,A) GTY \
473 VEC(T,B) base; \
474 } VEC(T,A)
476 /* Convert to base type. */
477 #define VEC_BASE(P) ((P) ? &(P)->base : 0)
479 /* Vector of integer-like object. */
480 #if IN_GENGTYPE
481 {"DEF_VEC_I", VEC_STRINGIFY (VEC_T(#0,#1)) ";", "none"},
482 {"DEF_VEC_ALLOC_I", VEC_STRINGIFY (VEC_TA (#0,#1,#2,#3)) ";", NULL},
483 #else
484 #define DEF_VEC_I(T) \
485 static inline void VEC_OP (T,must_be,integral_type) (void) \
487 (void)~(T)0; \
490 VEC_T(T,base); \
491 VEC_TA_GTY(T,base,none,); \
492 DEF_VEC_FUNC_P(T) \
493 struct vec_swallow_trailing_semi
494 #define DEF_VEC_ALLOC_I(T,A) \
495 VEC_TA_GTY(T,base,A,); \
496 DEF_VEC_ALLOC_FUNC_I(T,A) \
497 struct vec_swallow_trailing_semi
498 #endif
500 /* Vector of pointer to object. */
501 #if IN_GENGTYPE
502 {"DEF_VEC_P", VEC_STRINGIFY (VEC_T_GTY(#0,#1)) ";", "none"},
503 {"DEF_VEC_ALLOC_P", VEC_STRINGIFY (VEC_TA_GTY (#0,#1,#2,#3)) ";", NULL},
504 #else
505 #define DEF_VEC_P(T) \
506 static inline void VEC_OP (T,must_be,pointer_type) (void) \
508 (void)((T)1 == (void *)1); \
511 VEC_T_GTY(T,base); \
512 VEC_TA_GTY(T,base,none,); \
513 DEF_VEC_FUNC_P(T) \
514 struct vec_swallow_trailing_semi
515 #define DEF_VEC_ALLOC_P(T,A) \
516 VEC_TA_GTY(T,base,A,); \
517 DEF_VEC_ALLOC_FUNC_P(T,A) \
518 struct vec_swallow_trailing_semi
519 #endif
521 #define DEF_VEC_FUNC_P(T) \
522 static inline unsigned VEC_OP (T,base,length) (const VEC(T,base) *vec_) \
524 return vec_ ? vec_->num : 0; \
527 static inline T VEC_OP (T,base,last) \
528 (const VEC(T,base) *vec_ VEC_CHECK_DECL) \
530 VEC_ASSERT (vec_ && vec_->num, "last", T, base); \
532 return vec_->vec[vec_->num - 1]; \
535 static inline T VEC_OP (T,base,index) \
536 (const VEC(T,base) *vec_, unsigned ix_ VEC_CHECK_DECL) \
538 VEC_ASSERT (vec_ && ix_ < vec_->num, "index", T, base); \
540 return vec_->vec[ix_]; \
543 static inline int VEC_OP (T,base,iterate) \
544 (const VEC(T,base) *vec_, unsigned ix_, T *ptr) \
546 if (vec_ && ix_ < vec_->num) \
548 *ptr = vec_->vec[ix_]; \
549 return 1; \
551 else \
553 *ptr = 0; \
554 return 0; \
558 static inline size_t VEC_OP (T,base,embedded_size) \
559 (int alloc_) \
561 return offsetof (VEC(T,base),vec) + alloc_ * sizeof(T); \
564 static inline void VEC_OP (T,base,embedded_init) \
565 (VEC(T,base) *vec_, int alloc_) \
567 vec_->num = 0; \
568 vec_->alloc = alloc_; \
571 static inline int VEC_OP (T,base,space) \
572 (VEC(T,base) *vec_, int alloc_ VEC_CHECK_DECL) \
574 VEC_ASSERT (alloc_ >= 0, "space", T, base); \
575 return vec_ ? vec_->alloc - vec_->num >= (unsigned)alloc_ : !alloc_; \
578 static inline T *VEC_OP (T,base,quick_push) \
579 (VEC(T,base) *vec_, T obj_ VEC_CHECK_DECL) \
581 T *slot_; \
583 VEC_ASSERT (vec_->num < vec_->alloc, "push", T, base); \
584 slot_ = &vec_->vec[vec_->num++]; \
585 *slot_ = obj_; \
587 return slot_; \
590 static inline T VEC_OP (T,base,pop) (VEC(T,base) *vec_ VEC_CHECK_DECL) \
592 T obj_; \
594 VEC_ASSERT (vec_->num, "pop", T, base); \
595 obj_ = vec_->vec[--vec_->num]; \
597 return obj_; \
600 static inline void VEC_OP (T,base,truncate) \
601 (VEC(T,base) *vec_, unsigned size_ VEC_CHECK_DECL) \
603 VEC_ASSERT (vec_ ? vec_->num >= size_ : !size_, "truncate", T, base); \
604 if (vec_) \
605 vec_->num = size_; \
608 static inline T VEC_OP (T,base,replace) \
609 (VEC(T,base) *vec_, unsigned ix_, T obj_ VEC_CHECK_DECL) \
611 T old_obj_; \
613 VEC_ASSERT (ix_ < vec_->num, "replace", T, base); \
614 old_obj_ = vec_->vec[ix_]; \
615 vec_->vec[ix_] = obj_; \
617 return old_obj_; \
620 static inline T *VEC_OP (T,base,quick_insert) \
621 (VEC(T,base) *vec_, unsigned ix_, T obj_ VEC_CHECK_DECL) \
623 T *slot_; \
625 VEC_ASSERT (vec_->num < vec_->alloc, "insert", T, base); \
626 VEC_ASSERT (ix_ <= vec_->num, "insert", T, base); \
627 slot_ = &vec_->vec[ix_]; \
628 memmove (slot_ + 1, slot_, (vec_->num++ - ix_) * sizeof (T)); \
629 *slot_ = obj_; \
631 return slot_; \
634 static inline T VEC_OP (T,base,ordered_remove) \
635 (VEC(T,base) *vec_, unsigned ix_ VEC_CHECK_DECL) \
637 T *slot_; \
638 T obj_; \
640 VEC_ASSERT (ix_ < vec_->num, "remove", T, base); \
641 slot_ = &vec_->vec[ix_]; \
642 obj_ = *slot_; \
643 memmove (slot_, slot_ + 1, (--vec_->num - ix_) * sizeof (T)); \
645 return obj_; \
648 static inline T VEC_OP (T,base,unordered_remove) \
649 (VEC(T,base) *vec_, unsigned ix_ VEC_CHECK_DECL) \
651 T *slot_; \
652 T obj_; \
654 VEC_ASSERT (ix_ < vec_->num, "remove", T, base); \
655 slot_ = &vec_->vec[ix_]; \
656 obj_ = *slot_; \
657 *slot_ = vec_->vec[--vec_->num]; \
659 return obj_; \
662 static inline void VEC_OP (T,base,block_remove) \
663 (VEC(T,base) *vec_, unsigned ix_, unsigned len_ VEC_CHECK_DECL) \
665 T *slot_; \
667 VEC_ASSERT (ix_ + len_ <= vec_->num, "block_remove", T, base); \
668 slot_ = &vec_->vec[ix_]; \
669 vec_->num -= len_; \
670 memmove (slot_, slot_ + len_, (vec_->num - ix_) * sizeof (T)); \
673 static inline T *VEC_OP (T,base,address) \
674 (VEC(T,base) *vec_) \
676 return vec_ ? vec_->vec : 0; \
679 static inline unsigned VEC_OP (T,base,lower_bound) \
680 (VEC(T,base) *vec_, const T obj_, \
681 bool (*lessthan_)(const T, const T) VEC_CHECK_DECL) \
683 unsigned int len_ = VEC_OP (T,base, length) (vec_); \
684 unsigned int half_, middle_; \
685 unsigned int first_ = 0; \
686 while (len_ > 0) \
688 T middle_elem_; \
689 half_ = len_ >> 1; \
690 middle_ = first_; \
691 middle_ += half_; \
692 middle_elem_ = VEC_OP (T,base,index) (vec_, middle_ VEC_CHECK_PASS); \
693 if (lessthan_ (middle_elem_, obj_)) \
695 first_ = middle_; \
696 ++first_; \
697 len_ = len_ - half_ - 1; \
699 else \
700 len_ = half_; \
702 return first_; \
705 #define DEF_VEC_ALLOC_FUNC_P(T,A) \
706 static inline VEC(T,A) *VEC_OP (T,A,alloc) \
707 (int alloc_ MEM_STAT_DECL) \
709 return (VEC(T,A) *) vec_##A##_p_reserve_exact (NULL, alloc_ \
710 PASS_MEM_STAT); \
713 static inline void VEC_OP (T,A,free) \
714 (VEC(T,A) **vec_) \
716 if (*vec_) \
717 vec_##A##_free (*vec_); \
718 *vec_ = NULL; \
721 static inline VEC(T,A) *VEC_OP (T,A,copy) (VEC(T,base) *vec_ MEM_STAT_DECL) \
723 size_t len_ = vec_ ? vec_->num : 0; \
724 VEC (T,A) *new_vec_ = NULL; \
726 if (len_) \
728 new_vec_ = (VEC (T,A) *)(vec_##A##_p_reserve_exact \
729 (NULL, len_ PASS_MEM_STAT)); \
731 new_vec_->base.num = len_; \
732 memcpy (new_vec_->base.vec, vec_->vec, sizeof (T) * len_); \
734 return new_vec_; \
737 static inline int VEC_OP (T,A,reserve) \
738 (VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL) \
740 int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_ \
741 VEC_CHECK_PASS); \
743 if (extend) \
744 *vec_ = (VEC(T,A) *) vec_##A##_p_reserve (*vec_, alloc_ PASS_MEM_STAT); \
746 return extend; \
749 static inline int VEC_OP (T,A,reserve_exact) \
750 (VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL) \
752 int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_ \
753 VEC_CHECK_PASS); \
755 if (extend) \
756 *vec_ = (VEC(T,A) *) vec_##A##_p_reserve_exact (*vec_, alloc_ \
757 PASS_MEM_STAT); \
759 return extend; \
762 static inline void VEC_OP (T,A,safe_grow) \
763 (VEC(T,A) **vec_, int size_ VEC_CHECK_DECL MEM_STAT_DECL) \
765 VEC_ASSERT (size_ >= 0 \
766 && VEC_OP(T,base,length) VEC_BASE(*vec_) <= (unsigned)size_, \
767 "grow", T, A); \
768 VEC_OP (T,A,reserve_exact) (vec_, \
769 size_ - (int)(*vec_ ? VEC_BASE(*vec_)->num : 0) \
770 VEC_CHECK_PASS PASS_MEM_STAT); \
771 VEC_BASE (*vec_)->num = size_; \
774 static inline T *VEC_OP (T,A,safe_push) \
775 (VEC(T,A) **vec_, T obj_ VEC_CHECK_DECL MEM_STAT_DECL) \
777 VEC_OP (T,A,reserve) (vec_, 1 VEC_CHECK_PASS PASS_MEM_STAT); \
779 return VEC_OP (T,base,quick_push) (VEC_BASE(*vec_), obj_ VEC_CHECK_PASS); \
782 static inline T *VEC_OP (T,A,safe_insert) \
783 (VEC(T,A) **vec_, unsigned ix_, T obj_ VEC_CHECK_DECL MEM_STAT_DECL) \
785 VEC_OP (T,A,reserve) (vec_, 1 VEC_CHECK_PASS PASS_MEM_STAT); \
787 return VEC_OP (T,base,quick_insert) (VEC_BASE(*vec_), ix_, obj_ \
788 VEC_CHECK_PASS); \
791 /* Vector of object. */
792 #if IN_GENGTYPE
793 {"DEF_VEC_O", VEC_STRINGIFY (VEC_T_GTY(#0,#1)) ";", "none"},
794 {"DEF_VEC_ALLOC_O", VEC_STRINGIFY (VEC_TA_GTY(#0,#1,#2,#3)) ";", NULL},
795 #else
796 #define DEF_VEC_O(T) \
797 VEC_T_GTY(T,base); \
798 VEC_TA_GTY(T,base,none,); \
799 DEF_VEC_FUNC_O(T) \
800 struct vec_swallow_trailing_semi
801 #define DEF_VEC_ALLOC_O(T,A) \
802 VEC_TA_GTY(T,base,A,); \
803 DEF_VEC_ALLOC_FUNC_O(T,A) \
804 struct vec_swallow_trailing_semi
805 #endif
807 #define DEF_VEC_FUNC_O(T) \
808 static inline unsigned VEC_OP (T,base,length) (const VEC(T,base) *vec_) \
810 return vec_ ? vec_->num : 0; \
813 static inline T *VEC_OP (T,base,last) (VEC(T,base) *vec_ VEC_CHECK_DECL) \
815 VEC_ASSERT (vec_ && vec_->num, "last", T, base); \
817 return &vec_->vec[vec_->num - 1]; \
820 static inline T *VEC_OP (T,base,index) \
821 (VEC(T,base) *vec_, unsigned ix_ VEC_CHECK_DECL) \
823 VEC_ASSERT (vec_ && ix_ < vec_->num, "index", T, base); \
825 return &vec_->vec[ix_]; \
828 static inline int VEC_OP (T,base,iterate) \
829 (VEC(T,base) *vec_, unsigned ix_, T **ptr) \
831 if (vec_ && ix_ < vec_->num) \
833 *ptr = &vec_->vec[ix_]; \
834 return 1; \
836 else \
838 *ptr = 0; \
839 return 0; \
843 static inline size_t VEC_OP (T,base,embedded_size) \
844 (int alloc_) \
846 return offsetof (VEC(T,base),vec) + alloc_ * sizeof(T); \
849 static inline void VEC_OP (T,base,embedded_init) \
850 (VEC(T,base) *vec_, int alloc_) \
852 vec_->num = 0; \
853 vec_->alloc = alloc_; \
856 static inline int VEC_OP (T,base,space) \
857 (VEC(T,base) *vec_, int alloc_ VEC_CHECK_DECL) \
859 VEC_ASSERT (alloc_ >= 0, "space", T, base); \
860 return vec_ ? vec_->alloc - vec_->num >= (unsigned)alloc_ : !alloc_; \
863 static inline T *VEC_OP (T,base,quick_push) \
864 (VEC(T,base) *vec_, const T *obj_ VEC_CHECK_DECL) \
866 T *slot_; \
868 VEC_ASSERT (vec_->num < vec_->alloc, "push", T, base); \
869 slot_ = &vec_->vec[vec_->num++]; \
870 if (obj_) \
871 *slot_ = *obj_; \
873 return slot_; \
876 static inline void VEC_OP (T,base,pop) (VEC(T,base) *vec_ VEC_CHECK_DECL) \
878 VEC_ASSERT (vec_->num, "pop", T, base); \
879 --vec_->num; \
882 static inline void VEC_OP (T,base,truncate) \
883 (VEC(T,base) *vec_, unsigned size_ VEC_CHECK_DECL) \
885 VEC_ASSERT (vec_ ? vec_->num >= size_ : !size_, "truncate", T, base); \
886 if (vec_) \
887 vec_->num = size_; \
890 static inline T *VEC_OP (T,base,replace) \
891 (VEC(T,base) *vec_, unsigned ix_, const T *obj_ VEC_CHECK_DECL) \
893 T *slot_; \
895 VEC_ASSERT (ix_ < vec_->num, "replace", T, base); \
896 slot_ = &vec_->vec[ix_]; \
897 if (obj_) \
898 *slot_ = *obj_; \
900 return slot_; \
903 static inline T *VEC_OP (T,base,quick_insert) \
904 (VEC(T,base) *vec_, unsigned ix_, const T *obj_ VEC_CHECK_DECL) \
906 T *slot_; \
908 VEC_ASSERT (vec_->num < vec_->alloc, "insert", T, base); \
909 VEC_ASSERT (ix_ <= vec_->num, "insert", T, base); \
910 slot_ = &vec_->vec[ix_]; \
911 memmove (slot_ + 1, slot_, (vec_->num++ - ix_) * sizeof (T)); \
912 if (obj_) \
913 *slot_ = *obj_; \
915 return slot_; \
918 static inline void VEC_OP (T,base,ordered_remove) \
919 (VEC(T,base) *vec_, unsigned ix_ VEC_CHECK_DECL) \
921 T *slot_; \
923 VEC_ASSERT (ix_ < vec_->num, "remove", T, base); \
924 slot_ = &vec_->vec[ix_]; \
925 memmove (slot_, slot_ + 1, (--vec_->num - ix_) * sizeof (T)); \
928 static inline void VEC_OP (T,base,unordered_remove) \
929 (VEC(T,base) *vec_, unsigned ix_ VEC_CHECK_DECL) \
931 VEC_ASSERT (ix_ < vec_->num, "remove", T, base); \
932 vec_->vec[ix_] = vec_->vec[--vec_->num]; \
935 static inline void VEC_OP (T,base,block_remove) \
936 (VEC(T,base) *vec_, unsigned ix_, unsigned len_ VEC_CHECK_DECL) \
938 T *slot_; \
940 VEC_ASSERT (ix_ + len_ <= vec_->num, "block_remove", T, base); \
941 slot_ = &vec_->vec[ix_]; \
942 vec_->num -= len_; \
943 memmove (slot_, slot_ + len_, (vec_->num - ix_) * sizeof (T)); \
946 static inline T *VEC_OP (T,base,address) \
947 (VEC(T,base) *vec_) \
949 return vec_ ? vec_->vec : 0; \
952 static inline unsigned VEC_OP (T,base,lower_bound) \
953 (VEC(T,base) *vec_, const T *obj_, \
954 bool (*lessthan_)(const T *, const T *) VEC_CHECK_DECL) \
956 unsigned int len_ = VEC_OP (T, base, length) (vec_); \
957 unsigned int half_, middle_; \
958 unsigned int first_ = 0; \
959 while (len_ > 0) \
961 T *middle_elem_; \
962 half_ = len_ >> 1; \
963 middle_ = first_; \
964 middle_ += half_; \
965 middle_elem_ = VEC_OP (T,base,index) (vec_, middle_ VEC_CHECK_PASS); \
966 if (lessthan_ (middle_elem_, obj_)) \
968 first_ = middle_; \
969 ++first_; \
970 len_ = len_ - half_ - 1; \
972 else \
973 len_ = half_; \
975 return first_; \
978 #define DEF_VEC_ALLOC_FUNC_O(T,A) \
979 static inline VEC(T,A) *VEC_OP (T,A,alloc) \
980 (int alloc_ MEM_STAT_DECL) \
982 return (VEC(T,A) *) vec_##A##_o_reserve_exact (NULL, alloc_, \
983 offsetof (VEC(T,A),base.vec), \
984 sizeof (T) \
985 PASS_MEM_STAT); \
988 static inline VEC(T,A) *VEC_OP (T,A,copy) (VEC(T,base) *vec_ MEM_STAT_DECL) \
990 size_t len_ = vec_ ? vec_->num : 0; \
991 VEC (T,A) *new_vec_ = NULL; \
993 if (len_) \
995 new_vec_ = (VEC (T,A) *)(vec_##A##_o_reserve_exact \
996 (NULL, len_, \
997 offsetof (VEC(T,A),base.vec), sizeof (T) \
998 PASS_MEM_STAT)); \
1000 new_vec_->base.num = len_; \
1001 memcpy (new_vec_->base.vec, vec_->vec, sizeof (T) * len_); \
1003 return new_vec_; \
1006 static inline void VEC_OP (T,A,free) \
1007 (VEC(T,A) **vec_) \
1009 if (*vec_) \
1010 vec_##A##_free (*vec_); \
1011 *vec_ = NULL; \
1014 static inline int VEC_OP (T,A,reserve) \
1015 (VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL) \
1017 int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_ \
1018 VEC_CHECK_PASS); \
1020 if (extend) \
1021 *vec_ = (VEC(T,A) *) vec_##A##_o_reserve (*vec_, alloc_, \
1022 offsetof (VEC(T,A),base.vec),\
1023 sizeof (T) \
1024 PASS_MEM_STAT); \
1026 return extend; \
1029 static inline int VEC_OP (T,A,reserve_exact) \
1030 (VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL) \
1032 int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_ \
1033 VEC_CHECK_PASS); \
1035 if (extend) \
1036 *vec_ = (VEC(T,A) *) vec_##A##_o_reserve_exact \
1037 (*vec_, alloc_, \
1038 offsetof (VEC(T,A),base.vec), \
1039 sizeof (T) PASS_MEM_STAT); \
1041 return extend; \
1044 static inline void VEC_OP (T,A,safe_grow) \
1045 (VEC(T,A) **vec_, int size_ VEC_CHECK_DECL MEM_STAT_DECL) \
1047 VEC_ASSERT (size_ >= 0 \
1048 && VEC_OP(T,base,length) VEC_BASE(*vec_) <= (unsigned)size_, \
1049 "grow", T, A); \
1050 VEC_OP (T,A,reserve_exact) (vec_, \
1051 size_ - (int)(*vec_ ? VEC_BASE(*vec_)->num : 0) \
1052 VEC_CHECK_PASS PASS_MEM_STAT); \
1053 VEC_BASE (*vec_)->num = size_; \
1056 static inline T *VEC_OP (T,A,safe_push) \
1057 (VEC(T,A) **vec_, const T *obj_ VEC_CHECK_DECL MEM_STAT_DECL) \
1059 VEC_OP (T,A,reserve) (vec_, 1 VEC_CHECK_PASS PASS_MEM_STAT); \
1061 return VEC_OP (T,base,quick_push) (VEC_BASE(*vec_), obj_ VEC_CHECK_PASS); \
1064 static inline T *VEC_OP (T,A,safe_insert) \
1065 (VEC(T,A) **vec_, unsigned ix_, const T *obj_ \
1066 VEC_CHECK_DECL MEM_STAT_DECL) \
1068 VEC_OP (T,A,reserve) (vec_, 1 VEC_CHECK_PASS PASS_MEM_STAT); \
1070 return VEC_OP (T,base,quick_insert) (VEC_BASE(*vec_), ix_, obj_ \
1071 VEC_CHECK_PASS); \
1074 #define DEF_VEC_ALLOC_FUNC_I(T,A) \
1075 static inline VEC(T,A) *VEC_OP (T,A,alloc) \
1076 (int alloc_ MEM_STAT_DECL) \
1078 return (VEC(T,A) *) vec_##A##_o_reserve_exact \
1079 (NULL, alloc_, offsetof (VEC(T,A),base.vec), \
1080 sizeof (T) PASS_MEM_STAT); \
1083 static inline VEC(T,A) *VEC_OP (T,A,copy) (VEC(T,base) *vec_ MEM_STAT_DECL) \
1085 size_t len_ = vec_ ? vec_->num : 0; \
1086 VEC (T,A) *new_vec_ = NULL; \
1088 if (len_) \
1090 new_vec_ = (VEC (T,A) *)(vec_##A##_o_reserve_exact \
1091 (NULL, len_, \
1092 offsetof (VEC(T,A),base.vec), sizeof (T) \
1093 PASS_MEM_STAT)); \
1095 new_vec_->base.num = len_; \
1096 memcpy (new_vec_->base.vec, vec_->vec, sizeof (T) * len_); \
1098 return new_vec_; \
1101 static inline void VEC_OP (T,A,free) \
1102 (VEC(T,A) **vec_) \
1104 if (*vec_) \
1105 vec_##A##_free (*vec_); \
1106 *vec_ = NULL; \
1109 static inline int VEC_OP (T,A,reserve) \
1110 (VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL) \
1112 int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_ \
1113 VEC_CHECK_PASS); \
1115 if (extend) \
1116 *vec_ = (VEC(T,A) *) vec_##A##_o_reserve (*vec_, alloc_, \
1117 offsetof (VEC(T,A),base.vec),\
1118 sizeof (T) \
1119 PASS_MEM_STAT); \
1121 return extend; \
1124 static inline int VEC_OP (T,A,reserve_exact) \
1125 (VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL) \
1127 int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_ \
1128 VEC_CHECK_PASS); \
1130 if (extend) \
1131 *vec_ = (VEC(T,A) *) vec_##A##_o_reserve_exact \
1132 (*vec_, alloc_, offsetof (VEC(T,A),base.vec), \
1133 sizeof (T) PASS_MEM_STAT); \
1135 return extend; \
1138 static inline void VEC_OP (T,A,safe_grow) \
1139 (VEC(T,A) **vec_, int size_ VEC_CHECK_DECL MEM_STAT_DECL) \
1141 VEC_ASSERT (size_ >= 0 \
1142 && VEC_OP(T,base,length) VEC_BASE(*vec_) <= (unsigned)size_, \
1143 "grow", T, A); \
1144 VEC_OP (T,A,reserve_exact) (vec_, \
1145 size_ - (int)(*vec_ ? VEC_BASE(*vec_)->num : 0) \
1146 VEC_CHECK_PASS PASS_MEM_STAT); \
1147 VEC_BASE (*vec_)->num = size_; \
1150 static inline T *VEC_OP (T,A,safe_push) \
1151 (VEC(T,A) **vec_, const T obj_ VEC_CHECK_DECL MEM_STAT_DECL) \
1153 VEC_OP (T,A,reserve) (vec_, 1 VEC_CHECK_PASS PASS_MEM_STAT); \
1155 return VEC_OP (T,base,quick_push) (VEC_BASE(*vec_), obj_ VEC_CHECK_PASS); \
1158 static inline T *VEC_OP (T,A,safe_insert) \
1159 (VEC(T,A) **vec_, unsigned ix_, const T obj_ \
1160 VEC_CHECK_DECL MEM_STAT_DECL) \
1162 VEC_OP (T,A,reserve) (vec_, 1 VEC_CHECK_PASS PASS_MEM_STAT); \
1164 return VEC_OP (T,base,quick_insert) (VEC_BASE(*vec_), ix_, obj_ \
1165 VEC_CHECK_PASS); \
1168 #endif /* GCC_VEC_H */