2005-04-29 Jim Tison <jtison@us.ibm.com>
[official-gcc.git] / gcc / vec.h
blob13c4ed6b654554b70ffaf7f6749dea2eb8fb479b
1 /* Vector API for GNU compiler.
2 Copyright (C) 2004, 2005 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 2, 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 COPYING. If not, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA. */
22 #ifndef GCC_VEC_H
23 #define GCC_VEC_H
25 /* The macros here implement a set of templated vector types and
26 associated interfaces. These templates are implemented with
27 macros, as we're not in C++ land. The interface functions are
28 typesafe and use static inline functions, sometimes backed by
29 out-of-line generic functions. The vectors are designed to
30 interoperate with the GTY machinery.
32 Because of the different behavior of objects and of pointers to
33 objects, there are two flavors. One to deal with a vector of
34 pointers to objects, and one to deal with a vector of objects
35 themselves. Both of these pass pointers to objects around -- in
36 the former case the pointers are stored into the vector and in the
37 latter case the pointers are dereferenced and the objects copied
38 into the vector. Therefore, when using a vector of pointers, the
39 objects pointed to must be long lived, but when dealing with a
40 vector of objects, the source objects need not be. The vector of
41 pointers API is also appropriate for small register sized objects
42 like integers.
44 There are both 'index' and 'iterate' accessors. The iterator
45 returns a boolean iteration condition and updates the iteration
46 variable passed by reference. Because the iterator will be
47 inlined, the address-of can be optimized away.
49 The vectors are implemented using the trailing array idiom, thus
50 they are not resizeable without changing the address of the vector
51 object itself. This means you cannot have variables or fields of
52 vector type -- always use a pointer to a vector. The one exception
53 is the final field of a structure, which could be a vector type.
54 You will have to use the embedded_size & embedded_init calls to
55 create such objects, and they will probably not be resizeable (so
56 don't use the 'safe' allocation variants). The trailing array
57 idiom is used (rather than a pointer to an array of data), because,
58 if we allow NULL to also represent an empty vector, empty vectors
59 occupy minimal space in the structure containing them.
61 Each operation that increases the number of active elements is
62 available in 'quick' and 'safe' variants. The former presumes that
63 there is sufficient allocated space for the operation to succeed
64 (it dies if there is not). The latter will reallocate the
65 vector, if needed. Reallocation causes an exponential increase in
66 vector size. If you know you will be adding N elements, it would
67 be more efficient to use the reserve operation before adding the
68 elements with the 'quick' operation. This will ensure there are at
69 least as many elements as you ask for, it will exponentially
70 increase if there are too few spare slots. If you want reserve a
71 specific number of slots, but do not want the exponential increase
72 (for instance, you know this is the last allocation), use a
73 negative number for reservation. You can also create a vector of a
74 specific size from the get go.
76 You should prefer the push and pop operations, as they append and
77 remove from the end of the vector. If you need to remove several
78 items in one go, use the truncate operation. The insert and remove
79 operations allow you to change elements in the middle of the
80 vector. There are two remove operations, one which preserves the
81 element ordering 'ordered_remove', and one which does not
82 'unordered_remove'. The latter function copies the end element
83 into the removed slot, rather than invoke a memmove operation. The
84 'lower_bound' function will determine where to place an item in the
85 array using insert that will maintain sorted order.
87 When a vector type is defined, first a non-memory managed version
88 is created. You can then define either or both garbage collected
89 and heap allocated versions. The allocation mechanism is specified
90 when the type is defined, and is therefore part of the type. If
91 you need both gc'd and heap allocated versions, you still must have
92 *exactly* one definition of the common non-memory managed base vector.
94 If you need to directly manipulate a vector, then the 'address'
95 accessor will return the address of the start of the vector. Also
96 the 'space' predicate will tell you whether there is spare capacity
97 in the vector. You will not normally need to use these two functions.
99 Vector types are defined using a DEF_VEC_{O,P}(TYPEDEF) macro, to
100 get the non-memory allocation version, and then a
101 DEF_VEC_ALLOC_{O,P}(TYPEDEF,ALLOC) macro to get memory managed
102 vectors. Variables of vector type are declared using a
103 VEC(TYPEDEF,ALLOC) macro. The ALLOC argument specifies the
104 allocation strategy, and can be either 'gc' or 'heap' for garbage
105 collected and heap allocated respectively. It can be 'none' to get
106 a vector that must be explicitly allocated (for instance as a
107 trailing array of another structure). The characters O and P
108 indicate whether TYPEDEF is a pointer (P) or object (O) type. Be
109 careful to pick the correct one, as you'll get an awkward and
110 inefficient API if you get the wrong one. There is a check, which
111 results in a compile-time warning, for the P versions, but there is
112 no check for the O versions, as that is not possible in plain C.
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)))
149 /* Get the final element of the vector.
150 T VEC_T_last(VEC(T) *v); // Pointer
151 T *VEC_T_last(VEC(T) *v); // Object
153 Return the final element. V must not be empty. */
155 #define VEC_last(T,V) (VEC_OP(T,base,last)(VEC_BASE(V) VEC_CHECK_INFO))
157 /* Index into vector
158 T VEC_T_index(VEC(T) *v, unsigned ix); // Pointer
159 T *VEC_T_index(VEC(T) *v, unsigned ix); // Object
161 Return the IX'th element. If IX must be in the domain of V. */
163 #define VEC_index(T,V,I) (VEC_OP(T,base,index)(VEC_BASE(V),I VEC_CHECK_INFO))
165 /* Iterate over vector
166 int VEC_T_iterate(VEC(T) *v, unsigned ix, T &ptr); // Pointer
167 int VEC_T_iterate(VEC(T) *v, unsigned ix, T *&ptr); // Object
169 Return iteration condition and update PTR to point to the IX'th
170 element. At the end of iteration, sets PTR to NULL. Use this to
171 iterate over the elements of a vector as follows,
173 for (ix = 0; VEC_iterate(T,v,ix,ptr); ix++)
174 continue; */
176 #define VEC_iterate(T,V,I,P) (VEC_OP(T,base,iterate)(VEC_BASE(V),I,&(P)))
178 /* Allocate new vector.
179 VEC(T,A) *VEC_T_A_alloc(int reserve);
181 Allocate a new vector with space for RESERVE objects. If RESERVE
182 is zero, NO vector is created. */
184 #define VEC_alloc(T,A,N) (VEC_OP(T,A,alloc)(N MEM_STAT_INFO))
186 /* Free a vector.
187 void VEC_T_A_free(VEC(T,A) *&);
189 Free a vector and set it to NULL. */
191 #define VEC_free(T,A,V) (VEC_OP(T,A,free)(&V))
193 /* Use these to determine the required size and initialization of a
194 vector embedded within another structure (as the final member).
196 size_t VEC_T_embedded_size(int reserve);
197 void VEC_T_embedded_init(VEC(T) *v, int reserve);
199 These allow the caller to perform the memory allocation. */
201 #define VEC_embedded_size(T,N) (VEC_OP(T,base,embedded_size)(N))
202 #define VEC_embedded_init(T,O,N) (VEC_OP(T,base,embedded_init)(VEC_BASE(O),N))
204 /* Determine if a vector has additional capacity.
206 int VEC_T_space (VEC(T) *v,int reserve)
208 If V has space for RESERVE additional entries, return nonzero. You
209 usually only need to use this if you are doing your own vector
210 reallocation, for instance on an embedded vector. This returns
211 nonzero in exactly the same circumstances that VEC_T_reserve
212 will. */
214 #define VEC_space(T,V,R) \
215 (VEC_OP(T,base,space)(VEC_BASE(V),R VEC_CHECK_INFO))
217 /* Reserve space.
218 int VEC_T_A_reserve(VEC(T,A) *&v, int reserve);
220 Ensure that V has at least abs(RESERVE) slots available. The
221 signedness of RESERVE determines the reallocation behavior. A
222 negative value will not create additional headroom beyond that
223 requested. A positive value will create additional headroom. Note
224 this can cause V to be reallocated. Returns nonzero iff
225 reallocation actually occurred. */
227 #define VEC_reserve(T,A,V,R) \
228 (VEC_OP(T,A,reserve)(&(V),R VEC_CHECK_INFO MEM_STAT_INFO))
230 /* Push object with no reallocation
231 T *VEC_T_quick_push (VEC(T) *v, T obj); // Pointer
232 T *VEC_T_quick_push (VEC(T) *v, T *obj); // Object
234 Push a new element onto the end, returns a pointer to the slot
235 filled in. For object vectors, the new value can be NULL, in which
236 case NO initialization is performed. There must
237 be sufficient space in the vector. */
239 #define VEC_quick_push(T,V,O) \
240 (VEC_OP(T,base,quick_push)(VEC_BASE(V),O VEC_CHECK_INFO))
242 /* Push object with reallocation
243 T *VEC_T_A_safe_push (VEC(T,A) *&v, T obj); // Pointer
244 T *VEC_T_A_safe_push (VEC(T,A) *&v, T *obj); // Object
246 Push a new element onto the end, returns a pointer to the slot
247 filled in. For object vectors, the new value can be NULL, in which
248 case NO initialization is performed. Reallocates V, if needed. */
250 #define VEC_safe_push(T,A,V,O) \
251 (VEC_OP(T,A,safe_push)(&(V),O VEC_CHECK_INFO MEM_STAT_INFO))
253 /* Pop element off end
254 T VEC_T_pop (VEC(T) *v); // Pointer
255 void VEC_T_pop (VEC(T) *v); // Object
257 Pop the last element off the end. Returns the element popped, for
258 pointer vectors. */
260 #define VEC_pop(T,V) (VEC_OP(T,base,pop)(VEC_BASE(V) VEC_CHECK_INFO))
262 /* Truncate to specific length
263 void VEC_T_truncate (VEC(T) *v, unsigned len);
265 Set the length as specified. The new length must be less than or
266 equal to the current length. This is an O(1) operation. */
268 #define VEC_truncate(T,V,I) \
269 (VEC_OP(T,base,truncate)(VEC_BASE(V),I VEC_CHECK_INFO))
271 /* Grow to a specific length.
272 void VEC_T_A_safe_grow (VEC(T,A) *&v, int len);
274 Grow the vector to a specific length. The LEN must be as
275 long or longer than the current length. The new elements are
276 uninitialized. */
278 #define VEC_safe_grow(T,A,V,I) \
279 (VEC_OP(T,A,safe_grow)(&(V),I VEC_CHECK_INFO))
281 /* Replace element
282 T VEC_T_replace (VEC(T) *v, unsigned ix, T val); // Pointer
283 T *VEC_T_replace (VEC(T) *v, unsigned ix, T *val); // Object
285 Replace the IXth element of V with a new value, VAL. For pointer
286 vectors returns the original value. For object vectors returns a
287 pointer to the new value. For object vectors the new value can be
288 NULL, in which case no overwriting of the slot is actually
289 performed. */
291 #define VEC_replace(T,V,I,O) \
292 (VEC_OP(T,base,replace)(VEC_BASE(V),I,O VEC_CHECK_INFO))
294 /* Insert object with no reallocation
295 T *VEC_T_quick_insert (VEC(T) *v, unsigned ix, T val); // Pointer
296 T *VEC_T_quick_insert (VEC(T) *v, unsigned ix, T *val); // Object
298 Insert an element, VAL, at the IXth position of V. Return a pointer
299 to the slot created. For vectors of object, the new value can be
300 NULL, in which case no initialization of the inserted slot takes
301 place. There must be sufficient space. */
303 #define VEC_quick_insert(T,V,I,O) \
304 (VEC_OP(T,base,quick_insert)(VEC_BASE(V),I,O VEC_CHECK_INFO))
306 /* Insert object with reallocation
307 T *VEC_T_A_safe_insert (VEC(T,A) *&v, unsigned ix, T val); // Pointer
308 T *VEC_T_A_safe_insert (VEC(T,A) *&v, unsigned ix, T *val); // Object
310 Insert an element, VAL, at the IXth position of V. Return a pointer
311 to the slot created. For vectors of object, the new value can be
312 NULL, in which case no initialization of the inserted slot takes
313 place. Reallocate V, if necessary. */
315 #define VEC_safe_insert(T,A,V,I,O) \
316 (VEC_OP(T,A,safe_insert)(&(V),I,O VEC_CHECK_INFO MEM_STAT_INFO))
318 /* Remove element retaining order
319 T VEC_T_ordered_remove (VEC(T) *v, unsigned ix); // Pointer
320 void VEC_T_ordered_remove (VEC(T) *v, unsigned ix); // Object
322 Remove an element from the IXth position of V. Ordering of
323 remaining elements is preserved. For pointer vectors returns the
324 removed object. This is an O(N) operation due to a memmove. */
326 #define VEC_ordered_remove(T,V,I) \
327 (VEC_OP(T,base,ordered_remove)(VEC_BASE(V),I VEC_CHECK_INFO))
329 /* Remove element destroying order
330 T VEC_T_unordered_remove (VEC(T) *v, unsigned ix); // Pointer
331 void VEC_T_unordered_remove (VEC(T) *v, unsigned ix); // Object
333 Remove an element from the IXth position of V. Ordering of
334 remaining elements is destroyed. For pointer vectors returns the
335 removed object. This is an O(1) operation. */
337 #define VEC_unordered_remove(T,V,I) \
338 (VEC_OP(T,base,unordered_remove)(VEC_BASE(V),I VEC_CHECK_INFO))
340 /* Get the address of the array of elements
341 T *VEC_T_address (VEC(T) v)
343 If you need to directly manipulate the array (for instance, you
344 want to feed it to qsort), use this accessor. */
346 #define VEC_address(T,V) (VEC_OP(T,base,address)(VEC_BASE(V)))
348 /* Find the first index in the vector not less than the object.
349 unsigned VEC_T_lower_bound (VEC(T) *v, const T val,
350 bool (*lessthan) (const T, const T)); // Pointer
351 unsigned VEC_T_lower_bound (VEC(T) *v, const T *val,
352 bool (*lessthan) (const T*, const T*)); // Object
354 Find the first position in which VAL could be inserted without
355 changing the ordering of V. LESSTHAN is a function that returns
356 true if the first argument is strictly less than the second. */
358 #define VEC_lower_bound(T,V,O,LT) \
359 (VEC_OP(T,base,lower_bound)(VEC_BASE(V),O,LT VEC_CHECK_INFO))
361 #if !IN_GENGTYPE
362 /* Reallocate an array of elements with prefix. */
363 extern void *vec_gc_p_reserve (void *, int MEM_STAT_DECL);
364 extern void *vec_gc_o_reserve (void *, int, size_t, size_t MEM_STAT_DECL);
365 extern void ggc_free (void *);
366 #define vec_gc_free(V) ggc_free (V)
367 extern void *vec_heap_p_reserve (void *, int MEM_STAT_DECL);
368 extern void *vec_heap_o_reserve (void *, int, size_t, size_t MEM_STAT_DECL);
369 #define vec_heap_free(V) free (V)
371 #if ENABLE_CHECKING
372 #define VEC_CHECK_INFO ,__FILE__,__LINE__,__FUNCTION__
373 #define VEC_CHECK_DECL ,const char *file_,unsigned line_,const char *function_
374 #define VEC_CHECK_PASS ,file_,line_,function_
376 #define VEC_ASSERT(EXPR,OP,T,A) \
377 (void)((EXPR) ? 0 : (VEC_ASSERT_FAIL(OP,VEC(T,A)), 0))
379 extern void vec_assert_fail (const char *, const char * VEC_CHECK_DECL)
380 ATTRIBUTE_NORETURN;
381 #define VEC_ASSERT_FAIL(OP,VEC) vec_assert_fail (OP,#VEC VEC_CHECK_PASS)
382 #else
383 #define VEC_CHECK_INFO
384 #define VEC_CHECK_DECL
385 #define VEC_CHECK_PASS
386 #define VEC_ASSERT(EXPR,OP,T,A) (void)(EXPR)
387 #endif
389 #define VEC(T,A) VEC_##T##_##A
390 #define VEC_OP(T,A,OP) VEC_##T##_##A##_##OP
391 #else /* IN_GENGTYPE */
392 #define VEC(T,A) VEC_ T _ A
393 #define VEC_STRINGIFY(X) VEC_STRINGIFY_(X)
394 #define VEC_STRINGIFY_(X) #X
395 #undef GTY
396 #endif /* IN_GENGTYPE */
398 /* Base of vector type, not user visible. */
399 #define VEC_T(T,B) \
400 typedef struct VEC(T,B) GTY(()) \
402 unsigned num; \
403 unsigned alloc; \
404 T GTY ((length ("%h.num"))) vec[1]; \
405 } VEC(T,B)
407 /* Derived vector type, user visible. */
408 #define VEC_TA(T,B,A,GTY) \
409 typedef struct VEC(T,A) GTY \
411 VEC(T,B) base; \
412 } VEC(T,A)
414 /* Convert to base type. */
415 #define VEC_BASE(P) ((P) ? &(P)->base : 0)
417 /* Vector of pointer to object. */
418 #if IN_GENGTYPE
419 {"DEF_VEC_P", VEC_STRINGIFY (VEC_T(#0,#1)) ";", "none"},
420 {"DEF_VEC_ALLOC_P", VEC_STRINGIFY (VEC_TA (#0,#1,#2,#3)) ";", NULL},
421 #else
423 #define DEF_VEC_P(T) \
424 VEC_T(T,base); \
426 static inline void VEC_OP (T,must,be_a_pointer_or_integer) (void) \
428 (void)((T)0 == (void *)0); \
431 static inline unsigned VEC_OP (T,base,length) (const VEC(T,base) *vec_) \
433 return vec_ ? vec_->num : 0; \
436 static inline T VEC_OP (T,base,last) \
437 (const VEC(T,base) *vec_ VEC_CHECK_DECL) \
439 VEC_ASSERT (vec_ && vec_->num, "last", T, base); \
441 return vec_->vec[vec_->num - 1]; \
444 static inline T VEC_OP (T,base,index) \
445 (const VEC(T,base) *vec_, unsigned ix_ VEC_CHECK_DECL) \
447 VEC_ASSERT (vec_ && ix_ < vec_->num, "index", T, base); \
449 return vec_->vec[ix_]; \
452 static inline int VEC_OP (T,base,iterate) \
453 (const VEC(T,base) *vec_, unsigned ix_, T *ptr) \
455 if (vec_ && ix_ < vec_->num) \
457 *ptr = vec_->vec[ix_]; \
458 return 1; \
460 else \
462 *ptr = 0; \
463 return 0; \
467 static inline size_t VEC_OP (T,base,embedded_size) \
468 (int alloc_) \
470 return offsetof (VEC(T,base),vec) + alloc_ * sizeof(T); \
473 static inline void VEC_OP (T,base,embedded_init) \
474 (VEC(T,base) *vec_, int alloc_) \
476 vec_->num = 0; \
477 vec_->alloc = alloc_; \
480 static inline int VEC_OP (T,base,space) \
481 (VEC(T,base) *vec_, int alloc_ VEC_CHECK_DECL) \
483 VEC_ASSERT (alloc_ >= 0, "space", T, base); \
484 return vec_ ? vec_->alloc - vec_->num >= (unsigned)alloc_ : !alloc_; \
487 static inline T *VEC_OP (T,base,quick_push) \
488 (VEC(T,base) *vec_, T obj_ VEC_CHECK_DECL) \
490 T *slot_; \
492 VEC_ASSERT (vec_->num < vec_->alloc, "push", T, base); \
493 slot_ = &vec_->vec[vec_->num++]; \
494 *slot_ = obj_; \
496 return slot_; \
499 static inline T VEC_OP (T,base,pop) (VEC(T,base) *vec_ VEC_CHECK_DECL) \
501 T obj_; \
503 VEC_ASSERT (vec_->num, "pop", T, base); \
504 obj_ = vec_->vec[--vec_->num]; \
506 return obj_; \
509 static inline void VEC_OP (T,base,truncate) \
510 (VEC(T,base) *vec_, unsigned size_ VEC_CHECK_DECL) \
512 VEC_ASSERT (vec_ ? vec_->num >= size_ : !size_, "truncate", T, base); \
513 if (vec_) \
514 vec_->num = size_; \
517 static inline T VEC_OP (T,base,replace) \
518 (VEC(T,base) *vec_, unsigned ix_, T obj_ VEC_CHECK_DECL) \
520 T old_obj_; \
522 VEC_ASSERT (ix_ < vec_->num, "replace", T, base); \
523 old_obj_ = vec_->vec[ix_]; \
524 vec_->vec[ix_] = obj_; \
526 return old_obj_; \
529 static inline T *VEC_OP (T,base,quick_insert) \
530 (VEC(T,base) *vec_, unsigned ix_, T obj_ VEC_CHECK_DECL) \
532 T *slot_; \
534 VEC_ASSERT (vec_->num < vec_->alloc, "insert", T, base); \
535 VEC_ASSERT (ix_ <= vec_->num, "insert", T, base); \
536 slot_ = &vec_->vec[ix_]; \
537 memmove (slot_ + 1, slot_, (vec_->num++ - ix_) * sizeof (T)); \
538 *slot_ = obj_; \
540 return slot_; \
543 static inline T VEC_OP (T,base,ordered_remove) \
544 (VEC(T,base) *vec_, unsigned ix_ VEC_CHECK_DECL) \
546 T *slot_; \
547 T obj_; \
549 VEC_ASSERT (ix_ < vec_->num, "remove", T, base); \
550 slot_ = &vec_->vec[ix_]; \
551 obj_ = *slot_; \
552 memmove (slot_, slot_ + 1, (--vec_->num - ix_) * sizeof (T)); \
554 return obj_; \
557 static inline T VEC_OP (T,base,unordered_remove) \
558 (VEC(T,base) *vec_, unsigned ix_ VEC_CHECK_DECL) \
560 T *slot_; \
561 T obj_; \
563 VEC_ASSERT (ix_ < vec_->num, "remove", T, base); \
564 slot_ = &vec_->vec[ix_]; \
565 obj_ = *slot_; \
566 *slot_ = vec_->vec[--vec_->num]; \
568 return obj_; \
571 static inline T *VEC_OP (T,base,address) \
572 (VEC(T,base) *vec_) \
574 return vec_ ? vec_->vec : 0; \
577 static inline unsigned VEC_OP (T,base,lower_bound) \
578 (VEC(T,base) *vec_, const T obj_, \
579 bool (*lessthan_)(const T, const T) VEC_CHECK_DECL) \
581 unsigned int len_ = VEC_OP (T,base, length) (vec_); \
582 unsigned int half_, middle_; \
583 unsigned int first_ = 0; \
584 while (len_ > 0) \
586 T middle_elem_; \
587 half_ = len_ >> 1; \
588 middle_ = first_; \
589 middle_ += half_; \
590 middle_elem_ = VEC_OP (T,base,index) (vec_, middle_ VEC_CHECK_PASS); \
591 if (lessthan_ (middle_elem_, obj_)) \
593 first_ = middle_; \
594 ++first_; \
595 len_ = len_ - half_ - 1; \
597 else \
598 len_ = half_; \
600 return first_; \
603 VEC_TA(T,base,none,)
605 #define DEF_VEC_ALLOC_P(T,A) \
606 VEC_TA(T,base,A,); \
608 static inline VEC(T,A) *VEC_OP (T,A,alloc) \
609 (int alloc_ MEM_STAT_DECL) \
611 /* We must request exact size allocation, hence the negation. */ \
612 return (VEC(T,A) *) vec_##A##_p_reserve (NULL, -alloc_ PASS_MEM_STAT); \
615 static inline void VEC_OP (T,A,free) \
616 (VEC(T,A) **vec_) \
618 if (*vec_) \
619 vec_##A##_free (*vec_); \
620 *vec_ = NULL; \
623 static inline int VEC_OP (T,A,reserve) \
624 (VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL) \
626 int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), \
627 alloc_ < 0 ? -alloc_ : alloc_ \
628 VEC_CHECK_PASS); \
630 if (extend) \
631 *vec_ = (VEC(T,A) *) vec_##A##_p_reserve (*vec_, alloc_ PASS_MEM_STAT); \
633 return extend; \
636 static inline void VEC_OP (T,A,safe_grow) \
637 (VEC(T,A) **vec_, int size_ VEC_CHECK_DECL MEM_STAT_DECL) \
639 VEC_ASSERT (size_ >= 0 \
640 && VEC_OP(T,base,length) VEC_BASE(*vec_) <= (unsigned)size_, \
641 "grow", T, A); \
642 VEC_OP (T,A,reserve) (vec_, (int)(*vec_ ? VEC_BASE(*vec_)->num : 0) - size_ \
643 VEC_CHECK_PASS PASS_MEM_STAT); \
644 VEC_BASE (*vec_)->num = size_; \
647 static inline T *VEC_OP (T,A,safe_push) \
648 (VEC(T,A) **vec_, T obj_ VEC_CHECK_DECL MEM_STAT_DECL) \
650 VEC_OP (T,A,reserve) (vec_, 1 VEC_CHECK_PASS PASS_MEM_STAT); \
652 return VEC_OP (T,base,quick_push) (VEC_BASE(*vec_), obj_ VEC_CHECK_PASS); \
655 static inline T *VEC_OP (T,A,safe_insert) \
656 (VEC(T,A) **vec_, unsigned ix_, T obj_ VEC_CHECK_DECL MEM_STAT_DECL) \
658 VEC_OP (T,A,reserve) (vec_, 1 VEC_CHECK_PASS PASS_MEM_STAT); \
660 return VEC_OP (T,base,quick_insert) (VEC_BASE(*vec_), ix_, obj_ \
661 VEC_CHECK_PASS); \
664 struct vec_swallow_trailing_semi
665 #endif
667 /* Vector of object. */
668 #if IN_GENGTYPE
669 {"DEF_VEC_O", VEC_STRINGIFY (VEC_T(#0,#1)) ";", "none"},
670 {"DEF_VEC_ALLOC_O", VEC_STRINGIFY (VEC_TA(#0,#1,#2,#3)) ";", NULL},
671 #else
673 #define DEF_VEC_O(T) \
674 VEC_T(T,base); \
676 static inline unsigned VEC_OP (T,base,length) (const VEC(T,base) *vec_) \
678 return vec_ ? vec_->num : 0; \
681 static inline T *VEC_OP (T,base,last) (VEC(T,base) *vec_ VEC_CHECK_DECL) \
683 VEC_ASSERT (vec_ && vec_->num, "last", T, base); \
685 return &vec_->vec[vec_->num - 1]; \
688 static inline T *VEC_OP (T,base,index) \
689 (VEC(T,base) *vec_, unsigned ix_ VEC_CHECK_DECL) \
691 VEC_ASSERT (vec_ && ix_ < vec_->num, "index", T, base); \
693 return &vec_->vec[ix_]; \
696 static inline int VEC_OP (T,base,iterate) \
697 (VEC(T,base) *vec_, unsigned ix_, T **ptr) \
699 if (vec_ && ix_ < vec_->num) \
701 *ptr = &vec_->vec[ix_]; \
702 return 1; \
704 else \
706 *ptr = 0; \
707 return 0; \
711 static inline size_t VEC_OP (T,base,embedded_size) \
712 (int alloc_) \
714 return offsetof (VEC(T,base),vec) + alloc_ * sizeof(T); \
717 static inline void VEC_OP (T,base,embedded_init) \
718 (VEC(T,base) *vec_, int alloc_) \
720 vec_->num = 0; \
721 vec_->alloc = alloc_; \
724 static inline int VEC_OP (T,base,space) \
725 (VEC(T,base) *vec_, int alloc_ VEC_CHECK_DECL) \
727 VEC_ASSERT (alloc_ >= 0, "space", T, base); \
728 return vec_ ? vec_->alloc - vec_->num >= (unsigned)alloc_ : !alloc_; \
731 static inline T *VEC_OP (T,base,quick_push) \
732 (VEC(T,base) *vec_, const T *obj_ VEC_CHECK_DECL) \
734 T *slot_; \
736 VEC_ASSERT (vec_->num < vec_->alloc, "push", T, base); \
737 slot_ = &vec_->vec[vec_->num++]; \
738 if (obj_) \
739 *slot_ = *obj_; \
741 return slot_; \
744 static inline void VEC_OP (T,base,pop) (VEC(T,base) *vec_ VEC_CHECK_DECL) \
746 VEC_ASSERT (vec_->num, "pop", T, base); \
747 --vec_->num; \
750 static inline void VEC_OP (T,base,truncate) \
751 (VEC(T,base) *vec_, unsigned size_ VEC_CHECK_DECL) \
753 VEC_ASSERT (vec_ ? vec_->num >= size_ : !size_, "truncate", T, base); \
754 if (vec_) \
755 vec_->num = size_; \
758 static inline T *VEC_OP (T,base,replace) \
759 (VEC(T,base) *vec_, unsigned ix_, const T *obj_ VEC_CHECK_DECL) \
761 T *slot_; \
763 VEC_ASSERT (ix_ < vec_->num, "replace", T, base); \
764 slot_ = &vec_->vec[ix_]; \
765 if (obj_) \
766 *slot_ = *obj_; \
768 return slot_; \
771 static inline T *VEC_OP (T,base,quick_insert) \
772 (VEC(T,base) *vec_, unsigned ix_, const T *obj_ VEC_CHECK_DECL) \
774 T *slot_; \
776 VEC_ASSERT (vec_->num < vec_->alloc, "insert", T, base); \
777 VEC_ASSERT (ix_ <= vec_->num, "insert", T, base); \
778 slot_ = &vec_->vec[ix_]; \
779 memmove (slot_ + 1, slot_, (vec_->num++ - ix_) * sizeof (T)); \
780 if (obj_) \
781 *slot_ = *obj_; \
783 return slot_; \
786 static inline void VEC_OP (T,base,ordered_remove) \
787 (VEC(T,base) *vec_, unsigned ix_ VEC_CHECK_DECL) \
789 T *slot_; \
791 VEC_ASSERT (ix_ < vec_->num, "remove", T, base); \
792 slot_ = &vec_->vec[ix_]; \
793 memmove (slot_, slot_ + 1, (--vec_->num - ix_) * sizeof (T)); \
796 static inline void VEC_OP (T,base,unordered_remove) \
797 (VEC(T,base) *vec_, unsigned ix_ VEC_CHECK_DECL) \
799 VEC_ASSERT (ix_ < vec_->num, "remove", T, base); \
800 vec_->vec[ix_] = vec_->vec[--vec_->num]; \
803 static inline T *VEC_OP (T,base,address) \
804 (VEC(T,base) *vec_) \
806 return vec_ ? vec_->vec : 0; \
809 static inline unsigned VEC_OP (T,base,lower_bound) \
810 (VEC(T,base) *vec_, const T *obj_, \
811 bool (*lessthan_)(const T *, const T *) VEC_CHECK_DECL) \
813 unsigned int len_ = VEC_OP (T, base, length) (vec_); \
814 unsigned int half_, middle_; \
815 unsigned int first_ = 0; \
816 while (len_ > 0) \
818 T *middle_elem_; \
819 half_ = len_ >> 1; \
820 middle_ = first_; \
821 middle_ += half_; \
822 middle_elem_ = VEC_OP (T,base,index) (vec_, middle_ VEC_CHECK_PASS); \
823 if (lessthan_ (middle_elem_, obj_)) \
825 first_ = middle_; \
826 ++first_; \
827 len_ = len_ - half_ - 1; \
829 else \
830 len_ = half_; \
832 return first_; \
835 VEC_TA(T,base,none,)
837 #define DEF_VEC_ALLOC_O(T,A) \
838 VEC_TA(T,base,A,); \
840 static inline VEC(T,A) *VEC_OP (T,A,alloc) \
841 (int alloc_ MEM_STAT_DECL) \
843 /* We must request exact size allocation, hence the negation. */ \
844 return (VEC(T,A) *) vec_##A##_o_reserve (NULL, -alloc_, \
845 offsetof (VEC(T,A),base.vec), \
846 sizeof (T) \
847 PASS_MEM_STAT); \
850 static inline void VEC_OP (T,A,free) \
851 (VEC(T,A) **vec_) \
853 if (*vec_) \
854 vec_##A##_free (*vec_); \
855 *vec_ = NULL; \
858 static inline int VEC_OP (T,A,reserve) \
859 (VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL) \
861 int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), \
862 alloc_ < 0 ? -alloc_ : alloc_ \
863 VEC_CHECK_PASS); \
865 if (extend) \
866 *vec_ = (VEC(T,A) *) vec_##A##_o_reserve (*vec_, alloc_, \
867 offsetof (VEC(T,A),base.vec),\
868 sizeof (T) \
869 PASS_MEM_STAT); \
871 return extend; \
874 static inline void VEC_OP (T,A,safe_grow) \
875 (VEC(T,A) **vec_, int size_ VEC_CHECK_DECL MEM_STAT_DECL) \
877 VEC_ASSERT (size_ >= 0 \
878 && VEC_OP(T,base,length) VEC_BASE(*vec_) <= (unsigned)size_, \
879 "grow", T, A); \
880 VEC_OP (T,A,reserve) (vec_, (int)(*vec_ ? VEC_BASE(*vec_)->num : 0) - size_ \
881 VEC_CHECK_PASS PASS_MEM_STAT); \
882 VEC_BASE (*vec_)->num = size_; \
883 VEC_BASE (*vec_)->num = size_; \
886 static inline T *VEC_OP (T,A,safe_push) \
887 (VEC(T,A) **vec_, const T *obj_ VEC_CHECK_DECL MEM_STAT_DECL) \
889 VEC_OP (T,A,reserve) (vec_, 1 VEC_CHECK_PASS PASS_MEM_STAT); \
891 return VEC_OP (T,base,quick_push) (VEC_BASE(*vec_), obj_ VEC_CHECK_PASS); \
894 static inline T *VEC_OP (T,A,safe_insert) \
895 (VEC(T,A) **vec_, unsigned ix_, const T *obj_ \
896 VEC_CHECK_DECL MEM_STAT_DECL) \
898 VEC_OP (T,A,reserve) (vec_, 1 VEC_CHECK_PASS PASS_MEM_STAT); \
900 return VEC_OP (T,base,quick_insert) (VEC_BASE(*vec_), ix_, obj_ \
901 VEC_CHECK_PASS); \
904 struct vec_swallow_trailing_semi
905 #endif
907 #endif /* GCC_VEC_H */