http://gcc.gnu.org/ml/gcc-patches/2008-02/msg01094.html
[official-gcc.git] / gcc / vec.c
blob0ef1a6c5b6e90317c732d1e85b3cfdb96f19c7ac
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>
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 /* 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
29 #include "system.h"
30 #include "ggc.h"
31 #include "vec.h"
32 #include "coretypes.h"
33 #include "toplev.h"
35 struct vec_prefix
37 unsigned num;
38 unsigned alloc;
39 void *vec[1];
42 /* Calculate the new ALLOC value, making sure that RESERVE slots are
43 free. If EXACT grow exactly, otherwise grow exponentially. */
45 static inline unsigned
46 calculate_allocation (const struct vec_prefix *pfx, int reserve, bool exact)
48 unsigned alloc = 0;
49 unsigned num = 0;
51 gcc_assert (reserve >= 0);
53 if (pfx)
55 alloc = pfx->alloc;
56 num = pfx->num;
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;
63 /* We must have run out of room. */
64 gcc_assert (alloc - num < (unsigned) reserve);
66 if (exact)
67 /* Exact size. */
68 alloc = num + reserve;
69 else
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);
81 /* If this is still too small, set it to the right size. */
82 if (alloc < num + reserve)
83 alloc = num + reserve;
85 return alloc;
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. */
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)
98 struct vec_prefix *pfx = vec;
99 unsigned alloc = alloc = calculate_allocation (pfx, reserve, exact);
101 if (!alloc)
102 return NULL;
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;
109 return vec;
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. */
117 void *
118 vec_gc_p_reserve (void *vec, int reserve MEM_STAT_DECL)
120 return vec_gc_o_reserve_1 (vec, reserve,
121 offsetof (struct vec_prefix, vec),
122 sizeof (void *), false
123 PASS_MEM_STAT);
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. */
131 void *
132 vec_gc_p_reserve_exact (void *vec, int reserve MEM_STAT_DECL)
134 return vec_gc_o_reserve_1 (vec, reserve,
135 offsetof (struct vec_prefix, vec),
136 sizeof (void *), true
137 PASS_MEM_STAT);
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. */
144 void *
145 vec_gc_o_reserve (void *vec, int reserve, size_t vec_offset, size_t elt_size
146 MEM_STAT_DECL)
148 return vec_gc_o_reserve_1 (vec, reserve, vec_offset, elt_size, false
149 PASS_MEM_STAT);
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. */
156 void *
157 vec_gc_o_reserve_exact (void *vec, int reserve, size_t vec_offset,
158 size_t elt_size MEM_STAT_DECL)
160 return vec_gc_o_reserve_1 (vec, reserve, vec_offset, elt_size, true
161 PASS_MEM_STAT);
164 /* As for vec_gc_o_reserve_1, but for heap allocated vectors. */
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)
170 struct vec_prefix *pfx = vec;
171 unsigned alloc = calculate_allocation (pfx, reserve, exact);
173 if (!alloc)
174 return NULL;
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;
181 return vec;
184 /* As for vec_gc_p_reserve, but for heap allocated vectors. */
186 void *
187 vec_heap_p_reserve (void *vec, int reserve MEM_STAT_DECL)
189 return vec_heap_o_reserve_1 (vec, reserve,
190 offsetof (struct vec_prefix, vec),
191 sizeof (void *), false
192 PASS_MEM_STAT);
195 /* As for vec_gc_p_reserve_exact, but for heap allocated vectors. */
197 void *
198 vec_heap_p_reserve_exact (void *vec, int reserve MEM_STAT_DECL)
200 return vec_heap_o_reserve_1 (vec, reserve,
201 offsetof (struct vec_prefix, vec),
202 sizeof (void *), true
203 PASS_MEM_STAT);
206 /* As for vec_gc_o_reserve, but for heap allocated vectors. */
208 void *
209 vec_heap_o_reserve (void *vec, int reserve, size_t vec_offset, size_t elt_size
210 MEM_STAT_DECL)
212 return vec_heap_o_reserve_1 (vec, reserve, vec_offset, elt_size, false
213 PASS_MEM_STAT);
216 /* As for vec_gc_o_reserve_exact, but for heap allocated vectors. */
218 void *
219 vec_heap_o_reserve_exact (void *vec, int reserve, size_t vec_offset,
220 size_t elt_size MEM_STAT_DECL)
222 return vec_heap_o_reserve_1 (vec, reserve, vec_offset, elt_size, true
223 PASS_MEM_STAT);
226 #if ENABLE_CHECKING
227 /* Issue a vector domain error, and then fall over. */
229 void
230 vec_assert_fail (const char *op, const char *struct_name,
231 const char *file, unsigned int line, const char *function)
233 internal_error ("vector %s %s domain error, in %s at %s:%u",
234 struct_name, op, function, trim_filename (file), line);
236 #endif