190075Sobrien/* String pool for GCC.
2169689Skan   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
3169689Skan   Free Software Foundation, Inc.
490075Sobrien
590075SobrienThis file is part of GCC.
690075Sobrien
790075SobrienGCC is free software; you can redistribute it and/or modify it under
890075Sobrienthe terms of the GNU General Public License as published by the Free
990075SobrienSoftware Foundation; either version 2, or (at your option) any later
1090075Sobrienversion.
1190075Sobrien
1290075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1390075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or
1490075SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1590075Sobrienfor more details.
1690075Sobrien
1790075SobrienYou should have received a copy of the GNU General Public License
1890075Sobrienalong with GCC; see the file COPYING.  If not, write to the Free
19169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20169689Skan02110-1301, USA.  */
2190075Sobrien
2290075Sobrien/* String text, identifier text and identifier node allocator.  Strings
2390075Sobrien   allocated by ggc_alloc_string are stored in an obstack which is
2490075Sobrien   never shrunk.  Identifiers are uniquely stored in a hash table.
2590075Sobrien
26169689Skan   We use cpplib's hash table implementation.  libiberty's
2790075Sobrien   hashtab.c is not used because it requires 100% average space
2890075Sobrien   overhead per string, which is unacceptable.  Also, this algorithm
2990075Sobrien   is faster.  */
3090075Sobrien
3190075Sobrien#include "config.h"
3290075Sobrien#include "system.h"
33132718Skan#include "coretypes.h"
34132718Skan#include "tm.h"
3590075Sobrien#include "ggc.h"
3690075Sobrien#include "tree.h"
37169689Skan#include "symtab.h"
38132718Skan#include "cpplib.h"
3990075Sobrien
4090075Sobrien/* The "" allocated string.  */
4190075Sobrienconst char empty_string[] = "";
4290075Sobrien
4390075Sobrien/* Character strings, each containing a single decimal digit.
4490075Sobrien   Written this way to save space.  */
4590075Sobrienconst char digit_vector[] = {
4690075Sobrien  '0', 0, '1', 0, '2', 0, '3', 0, '4', 0,
4790075Sobrien  '5', 0, '6', 0, '7', 0, '8', 0, '9', 0
4890075Sobrien};
4990075Sobrien
5090075Sobrienstruct ht *ident_hash;
5190075Sobrienstatic struct obstack string_stack;
5290075Sobrien
53132718Skanstatic hashnode alloc_node (hash_table *);
54132718Skanstatic int mark_ident (struct cpp_reader *, hashnode, const void *);
5590075Sobrien
56169689Skanstatic void *
57169689Skanstringpool_ggc_alloc (size_t x)
58169689Skan{
59169689Skan  return ggc_alloc (x);
60169689Skan}
61169689Skan
6290075Sobrien/* Initialize the string pool.  */
6390075Sobrienvoid
64132718Skaninit_stringpool (void)
6590075Sobrien{
6690075Sobrien  /* Create with 16K (2^14) entries.  */
6790075Sobrien  ident_hash = ht_create (14);
6890075Sobrien  ident_hash->alloc_node = alloc_node;
69169689Skan  ident_hash->alloc_subobject = stringpool_ggc_alloc;
7090075Sobrien  gcc_obstack_init (&string_stack);
7190075Sobrien}
7290075Sobrien
7390075Sobrien/* Allocate a hash node.  */
7490075Sobrienstatic hashnode
75132718Skanalloc_node (hash_table *table ATTRIBUTE_UNUSED)
7690075Sobrien{
7790075Sobrien  return GCC_IDENT_TO_HT_IDENT (make_node (IDENTIFIER_NODE));
7890075Sobrien}
7990075Sobrien
8090075Sobrien/* Allocate and return a string constant of length LENGTH, containing
8190075Sobrien   CONTENTS.  If LENGTH is -1, CONTENTS is assumed to be a
8290075Sobrien   nul-terminated string, and the length is calculated using strlen.
8390075Sobrien   If the same string constant has been allocated before, that copy is
8490075Sobrien   returned this time too.  */
8590075Sobrien
8690075Sobrienconst char *
87132718Skanggc_alloc_string (const char *contents, int length)
8890075Sobrien{
8990075Sobrien  if (length == -1)
9090075Sobrien    length = strlen (contents);
9190075Sobrien
9290075Sobrien  if (length == 0)
9390075Sobrien    return empty_string;
9490075Sobrien  if (length == 1 && ISDIGIT (contents[0]))
9590075Sobrien    return digit_string (contents[0] - '0');
9690075Sobrien
9790075Sobrien  obstack_grow0 (&string_stack, contents, length);
98169689Skan  return XOBFINISH (&string_stack, const char *);
9990075Sobrien}
10090075Sobrien
10190075Sobrien/* Return an IDENTIFIER_NODE whose name is TEXT (a null-terminated string).
10290075Sobrien   If an identifier with that name has previously been referred to,
10390075Sobrien   the same node is returned this time.  */
10490075Sobrien
105132718Skan#undef get_identifier
106132718Skan
10790075Sobrientree
108132718Skanget_identifier (const char *text)
10990075Sobrien{
11090075Sobrien  hashnode ht_node = ht_lookup (ident_hash,
11190075Sobrien				(const unsigned char *) text,
11290075Sobrien				strlen (text), HT_ALLOC);
11390075Sobrien
11490075Sobrien  /* ht_node can't be NULL here.  */
11590075Sobrien  return HT_IDENT_TO_GCC_IDENT (ht_node);
11690075Sobrien}
11790075Sobrien
11890075Sobrien/* Identical to get_identifier, except that the length is assumed
11990075Sobrien   known.  */
120117395Skan
12190075Sobrientree
122132718Skanget_identifier_with_length (const char *text, size_t length)
12390075Sobrien{
12490075Sobrien  hashnode ht_node = ht_lookup (ident_hash,
12590075Sobrien				(const unsigned char *) text,
12690075Sobrien				length, HT_ALLOC);
12790075Sobrien
12890075Sobrien  /* ht_node can't be NULL here.  */
12990075Sobrien  return HT_IDENT_TO_GCC_IDENT (ht_node);
13090075Sobrien}
13190075Sobrien
13290075Sobrien/* If an identifier with the name TEXT (a null-terminated string) has
13390075Sobrien   previously been referred to, return that node; otherwise return
13490075Sobrien   NULL_TREE.  */
13590075Sobrien
13690075Sobrientree
137132718Skanmaybe_get_identifier (const char *text)
13890075Sobrien{
13990075Sobrien  hashnode ht_node;
14090075Sobrien
14190075Sobrien  ht_node = ht_lookup (ident_hash, (const unsigned char *) text,
14290075Sobrien		       strlen (text), HT_NO_INSERT);
14390075Sobrien  if (ht_node)
14490075Sobrien    return HT_IDENT_TO_GCC_IDENT (ht_node);
14590075Sobrien
14690075Sobrien  return NULL_TREE;
14790075Sobrien}
14890075Sobrien
14990075Sobrien/* Report some basic statistics about the string pool.  */
15090075Sobrien
15190075Sobrienvoid
152132718Skanstringpool_statistics (void)
15390075Sobrien{
15490075Sobrien  ht_dump_statistics (ident_hash);
15590075Sobrien}
156169689Skan
15790075Sobrien/* Mark an identifier for GC.  */
15890075Sobrien
15990075Sobrienstatic int
160132718Skanmark_ident (struct cpp_reader *pfile ATTRIBUTE_UNUSED, hashnode h,
161132718Skan	    const void *v ATTRIBUTE_UNUSED)
16290075Sobrien{
163132718Skan  gt_ggc_m_9tree_node (HT_IDENT_TO_GCC_IDENT (h));
16490075Sobrien  return 1;
16590075Sobrien}
16690075Sobrien
167132718Skan/* Mark the trees hanging off the identifier node for GGC.  These are
168132718Skan   handled specially (not using gengtype) because of the special
169132718Skan   treatment for strings.  */
17090075Sobrien
171132718Skanvoid
172132718Skanggc_mark_stringpool (void)
17390075Sobrien{
17490075Sobrien  ht_forall (ident_hash, mark_ident, NULL);
17590075Sobrien}
176132718Skan
177132718Skan/* Strings are _not_ GCed, but this routine exists so that a separate
178132718Skan   roots table isn't needed for the few global variables that refer
179132718Skan   to strings.  */
180132718Skan
181132718Skanvoid
182132718Skangt_ggc_m_S (void *x ATTRIBUTE_UNUSED)
183132718Skan{
184132718Skan}
185132718Skan
186132718Skan/* Pointer-walking routine for strings (not very interesting, since
187132718Skan   strings don't contain pointers).  */
188132718Skan
189132718Skanvoid
190132718Skangt_pch_p_S (void *obj ATTRIBUTE_UNUSED, void *x ATTRIBUTE_UNUSED,
191132718Skan	    gt_pointer_operator op ATTRIBUTE_UNUSED,
192132718Skan	    void *cookie ATTRIBUTE_UNUSED)
193132718Skan{
194132718Skan}
195132718Skan
196132718Skan/* PCH pointer-walking routine for strings.  */
197132718Skan
198132718Skanvoid
199132718Skangt_pch_n_S (const void *x)
200132718Skan{
201169689Skan  gt_pch_note_object ((void *)x, (void *)x, &gt_pch_p_S,
202169689Skan		      gt_types_enum_last);
203132718Skan}
204169689Skan
205132718Skan/* Handle saving and restoring the string pool for PCH.  */
206132718Skan
207169689Skan/* SPD is saved in the PCH file and holds the information needed
208169689Skan   to restore the string pool.  */
209169689Skan
210132718Skanstruct string_pool_data GTY(())
211132718Skan{
212169689Skan  struct ht_identifier * *
213169689Skan    GTY((length ("%h.nslots"),
214169689Skan	 nested_ptr (union tree_node, "%h ? GCC_IDENT_TO_HT_IDENT (%h) : NULL",
215169689Skan		     "%h ? HT_IDENT_TO_GCC_IDENT (%h) : NULL")))
216169689Skan    entries;
217132718Skan  unsigned int nslots;
218132718Skan  unsigned int nelements;
219132718Skan};
220132718Skan
221132718Skanstatic GTY(()) struct string_pool_data * spd;
222132718Skan
223169689Skan/* Save the stringpool data in SPD.  */
224132718Skan
225132718Skanvoid
226132718Skangt_pch_save_stringpool (void)
227132718Skan{
228132718Skan  spd = ggc_alloc (sizeof (*spd));
229132718Skan  spd->nslots = ident_hash->nslots;
230132718Skan  spd->nelements = ident_hash->nelements;
231169689Skan  spd->entries = ggc_alloc (sizeof (spd->entries[0]) * spd->nslots);
232169689Skan  memcpy (spd->entries, ident_hash->entries,
233169689Skan	  spd->nslots * sizeof (spd->entries[0]));
234132718Skan}
235132718Skan
236169689Skan/* Return the stringpool to its state before gt_pch_save_stringpool
237169689Skan   was called.  */
238169689Skan
239132718Skanvoid
240132718Skangt_pch_fixup_stringpool (void)
241132718Skan{
242132718Skan}
243132718Skan
244169689Skan/* A PCH file has been restored, which loaded SPD; fill the real hash table
245169689Skan   from SPD.  */
246169689Skan
247132718Skanvoid
248132718Skangt_pch_restore_stringpool (void)
249132718Skan{
250169689Skan  ht_load (ident_hash, spd->entries, spd->nslots, spd->nelements, false);
251132718Skan  spd = NULL;
252132718Skan}
253132718Skan
254132718Skan#include "gt-stringpool.h"
255