1169689Skan/* Vector API for GNU compiler.
2169689Skan   Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
3169689Skan   Contributed by Nathan Sidwell <nathan@codesourcery.com>
4169689Skan
5169689SkanThis file is part of GCC.
6169689Skan
7169689SkanGCC is free software; you can redistribute it and/or modify it under
8169689Skanthe terms of the GNU General Public License as published by the Free
9169689SkanSoftware Foundation; either version 2, or (at your option) any later
10169689Skanversion.
11169689Skan
12169689SkanGCC is distributed in the hope that it will be useful, but WITHOUT ANY
13169689SkanWARRANTY; without even the implied warranty of MERCHANTABILITY or
14169689SkanFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15169689Skanfor more details.
16169689Skan
17169689SkanYou should have received a copy of the GNU General Public License
18169689Skanalong with GCC; see the file COPYING.  If not, write to the Free
19169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20169689Skan02110-1301, USA.  */
21169689Skan
22169689Skan/* This file is compiled twice: once for the generator programs
23169689Skan   once for the compiler.  */
24169689Skan#ifdef GENERATOR_FILE
25169689Skan#include "bconfig.h"
26169689Skan#else
27169689Skan#include "config.h"
28169689Skan#endif
29169689Skan
30169689Skan#include "system.h"
31169689Skan#include "ggc.h"
32169689Skan#include "vec.h"
33169689Skan#include "coretypes.h"
34169689Skan#include "tree.h"
35169689Skan#include "toplev.h"
36169689Skan
37169689Skanstruct vec_prefix
38169689Skan{
39169689Skan  unsigned num;
40169689Skan  unsigned alloc;
41169689Skan  void *vec[1];
42169689Skan};
43169689Skan
44169689Skan/* Calculate the new ALLOC value, making sure that RESERVE slots are
45169689Skan   free.  If EXACT grow exactly, otherwise grow exponentially.  */
46169689Skan
47169689Skanstatic inline unsigned
48169689Skancalculate_allocation (const struct vec_prefix *pfx, int reserve, bool exact)
49169689Skan{
50169689Skan  unsigned alloc = 0;
51169689Skan  unsigned num = 0;
52169689Skan
53169689Skan  gcc_assert (reserve >= 0);
54169689Skan
55169689Skan  if (pfx)
56169689Skan    {
57169689Skan      alloc = pfx->alloc;
58169689Skan      num = pfx->num;
59169689Skan    }
60169689Skan  else if (!reserve)
61169689Skan    /* If there's no prefix, and we've not requested anything, then we
62169689Skan       will create a NULL vector.  */
63169689Skan    return 0;
64169689Skan
65169689Skan  /* We must have run out of room.  */
66169689Skan  gcc_assert (alloc - num < (unsigned) reserve);
67169689Skan
68169689Skan  if (exact)
69169689Skan    /* Exact size.  */
70169689Skan    alloc = num + reserve;
71169689Skan  else
72169689Skan    {
73169689Skan      /* Exponential growth. */
74169689Skan      if (!alloc)
75169689Skan	alloc = 4;
76169689Skan      else if (alloc < 16)
77169689Skan	/* Double when small.  */
78169689Skan	alloc = alloc * 2;
79169689Skan      else
80169689Skan	/* Grow slower when large.  */
81169689Skan	alloc = (alloc * 3 / 2);
82169689Skan
83169689Skan      /* If this is still too small, set it to the right size. */
84169689Skan      if (alloc < num + reserve)
85169689Skan	alloc = num + reserve;
86169689Skan    }
87169689Skan  return alloc;
88169689Skan}
89169689Skan
90169689Skan/* Ensure there are at least RESERVE free slots in VEC.  If EXACT grow
91169689Skan   exactly, else grow exponentially.  As a special case, if VEC is
92169689Skan   NULL and RESERVE is 0, no vector will be created.  The vector's
93169689Skan   trailing array is at VEC_OFFSET offset and consists of ELT_SIZE
94169689Skan   sized elements.  */
95169689Skan
96169689Skanstatic void *
97169689Skanvec_gc_o_reserve_1 (void *vec, int reserve, size_t vec_offset, size_t elt_size,
98169689Skan		    bool exact MEM_STAT_DECL)
99169689Skan{
100169689Skan  struct vec_prefix *pfx = vec;
101169689Skan  unsigned alloc = alloc = calculate_allocation (pfx, reserve, exact);
102169689Skan
103169689Skan  if (!alloc)
104169689Skan    return NULL;
105169689Skan
106169689Skan  vec = ggc_realloc_stat (vec, vec_offset + alloc * elt_size PASS_MEM_STAT);
107169689Skan  ((struct vec_prefix *)vec)->alloc = alloc;
108169689Skan  if (!pfx)
109169689Skan    ((struct vec_prefix *)vec)->num = 0;
110169689Skan
111169689Skan  return vec;
112169689Skan}
113169689Skan
114169689Skan/* Ensure there are at least RESERVE free slots in VEC, growing
115169689Skan   exponentially.  If RESERVE < 0 grow exactly, else grow
116169689Skan   exponentially.  As a special case, if VEC is NULL, and RESERVE is
117169689Skan   0, no vector will be created. */
118169689Skan
119169689Skanvoid *
120169689Skanvec_gc_p_reserve (void *vec, int reserve MEM_STAT_DECL)
121169689Skan{
122169689Skan  return vec_gc_o_reserve_1 (vec, reserve,
123169689Skan			     offsetof (struct vec_prefix, vec),
124169689Skan			     sizeof (void *), false
125169689Skan			     PASS_MEM_STAT);
126169689Skan}
127169689Skan
128169689Skan/* Ensure there are at least RESERVE free slots in VEC, growing
129169689Skan   exactly.  If RESERVE < 0 grow exactly, else grow exponentially.  As
130169689Skan   a special case, if VEC is NULL, and RESERVE is 0, no vector will be
131169689Skan   created. */
132169689Skan
133169689Skanvoid *
134169689Skanvec_gc_p_reserve_exact (void *vec, int reserve MEM_STAT_DECL)
135169689Skan{
136169689Skan  return vec_gc_o_reserve_1 (vec, reserve,
137169689Skan			     offsetof (struct vec_prefix, vec),
138169689Skan			     sizeof (void *), true
139169689Skan			     PASS_MEM_STAT);
140169689Skan}
141169689Skan
142169689Skan/* As for vec_gc_p_reserve, but for object vectors.  The vector's
143169689Skan   trailing array is at VEC_OFFSET offset and consists of ELT_SIZE
144169689Skan   sized elements.  */
145169689Skan
146169689Skanvoid *
147169689Skanvec_gc_o_reserve (void *vec, int reserve, size_t vec_offset, size_t elt_size
148169689Skan		  MEM_STAT_DECL)
149169689Skan{
150169689Skan  return vec_gc_o_reserve_1 (vec, reserve, vec_offset, elt_size, false
151169689Skan			     PASS_MEM_STAT);
152169689Skan}
153169689Skan
154169689Skan/* As for vec_gc_p_reserve_exact, but for object vectors.  The
155169689Skan   vector's trailing array is at VEC_OFFSET offset and consists of
156169689Skan   ELT_SIZE sized elements.  */
157169689Skan
158169689Skanvoid *
159169689Skanvec_gc_o_reserve_exact (void *vec, int reserve, size_t vec_offset,
160169689Skan			size_t elt_size MEM_STAT_DECL)
161169689Skan{
162169689Skan  return vec_gc_o_reserve_1 (vec, reserve, vec_offset, elt_size, true
163169689Skan			     PASS_MEM_STAT);
164169689Skan}
165169689Skan
166169689Skan/* As for vec_gc_o_reserve_1, but for heap allocated vectors.  */
167169689Skan
168169689Skanstatic void *
169169689Skanvec_heap_o_reserve_1 (void *vec, int reserve, size_t vec_offset,
170169689Skan		      size_t elt_size, bool exact MEM_STAT_DECL)
171169689Skan{
172169689Skan  struct vec_prefix *pfx = vec;
173169689Skan  unsigned alloc = calculate_allocation (pfx, reserve, exact);
174169689Skan
175169689Skan  if (!alloc)
176169689Skan    return NULL;
177169689Skan
178169689Skan  vec = xrealloc (vec, vec_offset + alloc * elt_size);
179169689Skan  ((struct vec_prefix *)vec)->alloc = alloc;
180169689Skan  if (!pfx)
181169689Skan    ((struct vec_prefix *)vec)->num = 0;
182169689Skan
183169689Skan  return vec;
184169689Skan}
185169689Skan
186169689Skan/* As for vec_gc_p_reserve, but for heap allocated vectors.  */
187169689Skan
188169689Skanvoid *
189169689Skanvec_heap_p_reserve (void *vec, int reserve MEM_STAT_DECL)
190169689Skan{
191169689Skan  return vec_heap_o_reserve_1 (vec, reserve,
192169689Skan			       offsetof (struct vec_prefix, vec),
193169689Skan			       sizeof (void *), false
194169689Skan			       PASS_MEM_STAT);
195169689Skan}
196169689Skan
197169689Skan/* As for vec_gc_p_reserve_exact, but for heap allocated vectors.  */
198169689Skan
199169689Skanvoid *
200169689Skanvec_heap_p_reserve_exact (void *vec, int reserve MEM_STAT_DECL)
201169689Skan{
202169689Skan  return vec_heap_o_reserve_1 (vec, reserve,
203169689Skan			       offsetof (struct vec_prefix, vec),
204169689Skan			       sizeof (void *), true
205169689Skan			       PASS_MEM_STAT);
206169689Skan}
207169689Skan
208169689Skan/* As for vec_gc_o_reserve, but for heap allocated vectors.  */
209169689Skan
210169689Skanvoid *
211169689Skanvec_heap_o_reserve (void *vec, int reserve, size_t vec_offset, size_t elt_size
212169689Skan		    MEM_STAT_DECL)
213169689Skan{
214169689Skan  return vec_heap_o_reserve_1 (vec, reserve, vec_offset, elt_size, false
215169689Skan			       PASS_MEM_STAT);
216169689Skan}
217169689Skan
218169689Skan/* As for vec_gc_o_reserve_exact, but for heap allocated vectors.  */
219169689Skan
220169689Skanvoid *
221169689Skanvec_heap_o_reserve_exact (void *vec, int reserve, size_t vec_offset,
222169689Skan			  size_t elt_size MEM_STAT_DECL)
223169689Skan{
224169689Skan  return vec_heap_o_reserve_1 (vec, reserve, vec_offset, elt_size, true
225169689Skan			       PASS_MEM_STAT);
226169689Skan}
227169689Skan
228169689Skan#if ENABLE_CHECKING
229169689Skan/* Issue a vector domain error, and then fall over.  */
230169689Skan
231169689Skanvoid
232169689Skanvec_assert_fail (const char *op, const char *struct_name,
233169689Skan		 const char *file, unsigned int line, const char *function)
234169689Skan{
235169689Skan  internal_error ("vector %s %s domain error, in %s at %s:%u",
236169689Skan		  struct_name, op, function, trim_filename (file), line);
237169689Skan}
238169689Skan#endif
239