ggc.h (GGC_RESIZEVAR): New, reorder macros.
[gcc.git] / gcc / vec.c
1 /* Vector API for GNU compiler.
2 Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
3 Contributed by Nathan Sidwell <nathan@codesourcery.com>
4
5 This file is part of GCC.
6
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.
11
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.
16
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/>. */
20
21 /* This file is compiled twice: once for the generator programs
22 once for the compiler. */
23 #ifdef GENERATOR_FILE
24 #include "bconfig.h"
25 #else
26 #include "config.h"
27 #endif
28
29 #include "system.h"
30 #include "ggc.h"
31 #include "vec.h"
32 #include "coretypes.h"
33 #include "toplev.h"
34
35 struct vec_prefix
36 {
37 unsigned num;
38 unsigned alloc;
39 void *vec[1];
40 };
41
42 /* Calculate the new ALLOC value, making sure that RESERVE slots are
43 free. If EXACT grow exactly, otherwise grow exponentially. */
44
45 static inline unsigned
46 calculate_allocation (const struct vec_prefix *pfx, int reserve, bool exact)
47 {
48 unsigned alloc = 0;
49 unsigned num = 0;
50
51 gcc_assert (reserve >= 0);
52
53 if (pfx)
54 {
55 alloc = pfx->alloc;
56 num = pfx->num;
57 }
58 else if (!reserve)
59 /* If there's no prefix, and we've not requested anything, then we
60 will create a NULL vector. */
61 return 0;
62
63 /* We must have run out of room. */
64 gcc_assert (alloc - num < (unsigned) reserve);
65
66 if (exact)
67 /* Exact size. */
68 alloc = num + reserve;
69 else
70 {
71 /* Exponential growth. */
72 if (!alloc)
73 alloc = 4;
74 else if (alloc < 16)
75 /* Double when small. */
76 alloc = alloc * 2;
77 else
78 /* Grow slower when large. */
79 alloc = (alloc * 3 / 2);
80
81 /* If this is still too small, set it to the right size. */
82 if (alloc < num + reserve)
83 alloc = num + reserve;
84 }
85 return alloc;
86 }
87
88 /* Ensure there are at least RESERVE free slots in VEC. If EXACT grow
89 exactly, else grow exponentially. As a special case, if VEC is
90 NULL and RESERVE is 0, no vector will be created. The vector's
91 trailing array is at VEC_OFFSET offset and consists of ELT_SIZE
92 sized elements. */
93
94 static void *
95 vec_gc_o_reserve_1 (void *vec, int reserve, size_t vec_offset, size_t elt_size,
96 bool exact MEM_STAT_DECL)
97 {
98 struct vec_prefix *pfx = (struct vec_prefix *) vec;
99 unsigned alloc = alloc = calculate_allocation (pfx, reserve, exact);
100
101 if (!alloc)
102 return NULL;
103
104 vec = ggc_realloc_stat (vec, vec_offset + alloc * elt_size PASS_MEM_STAT);
105 ((struct vec_prefix *)vec)->alloc = alloc;
106 if (!pfx)
107 ((struct vec_prefix *)vec)->num = 0;
108
109 return vec;
110 }
111
112 /* Ensure there are at least RESERVE free slots in VEC, growing
113 exponentially. If RESERVE < 0 grow exactly, else grow
114 exponentially. As a special case, if VEC is NULL, and RESERVE is
115 0, no vector will be created. */
116
117 void *
118 vec_gc_p_reserve (void *vec, int reserve MEM_STAT_DECL)
119 {
120 return vec_gc_o_reserve_1 (vec, reserve,
121 offsetof (struct vec_prefix, vec),
122 sizeof (void *), false
123 PASS_MEM_STAT);
124 }
125
126 /* Ensure there are at least RESERVE free slots in VEC, growing
127 exactly. If RESERVE < 0 grow exactly, else grow exponentially. As
128 a special case, if VEC is NULL, and RESERVE is 0, no vector will be
129 created. */
130
131 void *
132 vec_gc_p_reserve_exact (void *vec, int reserve MEM_STAT_DECL)
133 {
134 return vec_gc_o_reserve_1 (vec, reserve,
135 offsetof (struct vec_prefix, vec),
136 sizeof (void *), true
137 PASS_MEM_STAT);
138 }
139
140 /* As for vec_gc_p_reserve, but for object vectors. The vector's
141 trailing array is at VEC_OFFSET offset and consists of ELT_SIZE
142 sized elements. */
143
144 void *
145 vec_gc_o_reserve (void *vec, int reserve, size_t vec_offset, size_t elt_size
146 MEM_STAT_DECL)
147 {
148 return vec_gc_o_reserve_1 (vec, reserve, vec_offset, elt_size, false
149 PASS_MEM_STAT);
150 }
151
152 /* As for vec_gc_p_reserve_exact, but for object vectors. The
153 vector's trailing array is at VEC_OFFSET offset and consists of
154 ELT_SIZE sized elements. */
155
156 void *
157 vec_gc_o_reserve_exact (void *vec, int reserve, size_t vec_offset,
158 size_t elt_size MEM_STAT_DECL)
159 {
160 return vec_gc_o_reserve_1 (vec, reserve, vec_offset, elt_size, true
161 PASS_MEM_STAT);
162 }
163
164 /* As for vec_gc_o_reserve_1, but for heap allocated vectors. */
165
166 static void *
167 vec_heap_o_reserve_1 (void *vec, int reserve, size_t vec_offset,
168 size_t elt_size, bool exact MEM_STAT_DECL)
169 {
170 struct vec_prefix *pfx = (struct vec_prefix *) vec;
171 unsigned alloc = calculate_allocation (pfx, reserve, exact);
172
173 if (!alloc)
174 return NULL;
175
176 vec = xrealloc (vec, vec_offset + alloc * elt_size);
177 ((struct vec_prefix *)vec)->alloc = alloc;
178 if (!pfx)
179 ((struct vec_prefix *)vec)->num = 0;
180
181 return vec;
182 }
183
184 /* As for vec_gc_p_reserve, but for heap allocated vectors. */
185
186 void *
187 vec_heap_p_reserve (void *vec, int reserve MEM_STAT_DECL)
188 {
189 return vec_heap_o_reserve_1 (vec, reserve,
190 offsetof (struct vec_prefix, vec),
191 sizeof (void *), false
192 PASS_MEM_STAT);
193 }
194
195 /* As for vec_gc_p_reserve_exact, but for heap allocated vectors. */
196
197 void *
198 vec_heap_p_reserve_exact (void *vec, int reserve MEM_STAT_DECL)
199 {
200 return vec_heap_o_reserve_1 (vec, reserve,
201 offsetof (struct vec_prefix, vec),
202 sizeof (void *), true
203 PASS_MEM_STAT);
204 }
205
206 /* As for vec_gc_o_reserve, but for heap allocated vectors. */
207
208 void *
209 vec_heap_o_reserve (void *vec, int reserve, size_t vec_offset, size_t elt_size
210 MEM_STAT_DECL)
211 {
212 return vec_heap_o_reserve_1 (vec, reserve, vec_offset, elt_size, false
213 PASS_MEM_STAT);
214 }
215
216 /* As for vec_gc_o_reserve_exact, but for heap allocated vectors. */
217
218 void *
219 vec_heap_o_reserve_exact (void *vec, int reserve, size_t vec_offset,
220 size_t elt_size MEM_STAT_DECL)
221 {
222 return vec_heap_o_reserve_1 (vec, reserve, vec_offset, elt_size, true
223 PASS_MEM_STAT);
224 }
225
226 #if ENABLE_CHECKING
227 /* Issue a vector domain error, and then fall over. */
228
229 void
230 vec_assert_fail (const char *op, const char *struct_name,
231 const char *file, unsigned int line, const char *function)
232 {
233 internal_error ("vector %s %s domain error, in %s at %s:%u",
234 struct_name, op, function, trim_filename (file), line);
235 }
236 #endif