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