stringpool.c revision 117395
150397Sobrien/* String pool for GCC.
252284Sobrien   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
350397Sobrien
450397SobrienThis file is part of GCC.
550397Sobrien
650397SobrienGCC is free software; you can redistribute it and/or modify it under
750397Sobrienthe terms of the GNU General Public License as published by the Free
850397SobrienSoftware Foundation; either version 2, or (at your option) any later
950397Sobrienversion.
1050397Sobrien
1150397SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1250397SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or
1350397SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1450397Sobrienfor more details.
1550397Sobrien
1650397SobrienYou should have received a copy of the GNU General Public License
1750397Sobrienalong with GCC; see the file COPYING.  If not, write to the Free
1850397SobrienSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA
1950397Sobrien02111-1307, USA.  */
2050397Sobrien
2152284Sobrien/* String text, identifier text and identifier node allocator.  Strings
2252284Sobrien   allocated by ggc_alloc_string are stored in an obstack which is
2350397Sobrien   never shrunk.  Identifiers are uniquely stored in a hash table.
2450397Sobrien
2550397Sobrien   We have our own private hash table implementation.  libiberty's
2650397Sobrien   hashtab.c is not used because it requires 100% average space
2750397Sobrien   overhead per string, which is unacceptable.  Also, this algorithm
2850397Sobrien   is faster.  */
2950397Sobrien
3050397Sobrien#include "config.h"
3150397Sobrien#include "system.h"
3250397Sobrien#include "ggc.h"
3350397Sobrien#include "tree.h"
3450397Sobrien#include "hashtable.h"
3550397Sobrien
3650397Sobrien/* The "" allocated string.  */
3750397Sobrienconst char empty_string[] = "";
3850397Sobrien
3950397Sobrien/* Character strings, each containing a single decimal digit.
4050397Sobrien   Written this way to save space.  */
4150397Sobrienconst char digit_vector[] = {
4250397Sobrien  '0', 0, '1', 0, '2', 0, '3', 0, '4', 0,
4350397Sobrien  '5', 0, '6', 0, '7', 0, '8', 0, '9', 0
4450397Sobrien};
4550397Sobrien
4650397Sobrienstruct ht *ident_hash;
4750397Sobrienstatic struct obstack string_stack;
4850397Sobrien
4950397Sobrienstatic hashnode alloc_node PARAMS ((hash_table *));
5050397Sobrienstatic int mark_ident PARAMS ((struct cpp_reader *, hashnode, const PTR));
5150397Sobrienstatic void mark_ident_hash PARAMS ((void *));
5250397Sobrien
5350397Sobrien/* Initialize the string pool.  */
5450397Sobrienvoid
5550397Sobrieninit_stringpool ()
5650397Sobrien{
5750397Sobrien  /* Create with 16K (2^14) entries.  */
5850397Sobrien  ident_hash = ht_create (14);
5950397Sobrien  ident_hash->alloc_node = alloc_node;
6050397Sobrien  gcc_obstack_init (&string_stack);
6150397Sobrien  ggc_add_root (&ident_hash, 1, sizeof ident_hash, mark_ident_hash);
6250397Sobrien}
6350397Sobrien
6450397Sobrien/* Allocate a hash node.  */
6550397Sobrienstatic hashnode
6650397Sobrienalloc_node (table)
6750397Sobrien     hash_table *table ATTRIBUTE_UNUSED;
6850397Sobrien{
6950397Sobrien  return GCC_IDENT_TO_HT_IDENT (make_node (IDENTIFIER_NODE));
7050397Sobrien}
7150397Sobrien
7250397Sobrien/* Allocate and return a string constant of length LENGTH, containing
7350397Sobrien   CONTENTS.  If LENGTH is -1, CONTENTS is assumed to be a
7450397Sobrien   nul-terminated string, and the length is calculated using strlen.
7550397Sobrien   If the same string constant has been allocated before, that copy is
7650397Sobrien   returned this time too.  */
7750397Sobrien
7850397Sobrienconst char *
7950397Sobrienggc_alloc_string (contents, length)
8050397Sobrien     const char *contents;
8150397Sobrien     int length;
8250397Sobrien{
8350397Sobrien  if (length == -1)
8450397Sobrien    length = strlen (contents);
8550397Sobrien
8650397Sobrien  if (length == 0)
8750397Sobrien    return empty_string;
8850397Sobrien  if (length == 1 && ISDIGIT (contents[0]))
8950397Sobrien    return digit_string (contents[0] - '0');
9050397Sobrien
9150397Sobrien  obstack_grow0 (&string_stack, contents, length);
9250397Sobrien  return obstack_finish (&string_stack);
9350397Sobrien}
9450397Sobrien
9550397Sobrien/* Return an IDENTIFIER_NODE whose name is TEXT (a null-terminated string).
9650397Sobrien   If an identifier with that name has previously been referred to,
9750397Sobrien   the same node is returned this time.  */
9850397Sobrien
9950397Sobrientree
10050397Sobrienget_identifier (text)
10150397Sobrien     const char *text;
10250397Sobrien{
10350397Sobrien  hashnode ht_node = ht_lookup (ident_hash,
10450397Sobrien				(const unsigned char *) text,
10550397Sobrien				strlen (text), HT_ALLOC);
10650397Sobrien
10750397Sobrien  /* ht_node can't be NULL here.  */
10850397Sobrien  return HT_IDENT_TO_GCC_IDENT (ht_node);
10950397Sobrien}
11050397Sobrien
11150397Sobrien/* Identical to get_identifier, except that the length is assumed
11250397Sobrien   known.  */
11350397Sobrien
11450397Sobrientree
11550397Sobrienget_identifier_with_length (text, length)
11650397Sobrien     const char *text;
11750397Sobrien     unsigned int length;
11850397Sobrien{
11950397Sobrien  hashnode ht_node = ht_lookup (ident_hash,
12050397Sobrien				(const unsigned char *) text,
12150397Sobrien				length, HT_ALLOC);
12250397Sobrien
12350397Sobrien  /* ht_node can't be NULL here.  */
12450397Sobrien  return HT_IDENT_TO_GCC_IDENT (ht_node);
12550397Sobrien}
12650397Sobrien
12750397Sobrien/* If an identifier with the name TEXT (a null-terminated string) has
12850397Sobrien   previously been referred to, return that node; otherwise return
12950397Sobrien   NULL_TREE.  */
13050397Sobrien
13150397Sobrientree
13250397Sobrienmaybe_get_identifier (text)
13350397Sobrien     const char *text;
13450397Sobrien{
13550397Sobrien  hashnode ht_node;
13650397Sobrien
13750397Sobrien  ht_node = ht_lookup (ident_hash, (const unsigned char *) text,
13850397Sobrien		       strlen (text), HT_NO_INSERT);
13950397Sobrien  if (ht_node)
14050397Sobrien    return HT_IDENT_TO_GCC_IDENT (ht_node);
14150397Sobrien
14250397Sobrien  return NULL_TREE;
14350397Sobrien}
14450397Sobrien
14550397Sobrien/* Report some basic statistics about the string pool.  */
14650397Sobrien
14750397Sobrienvoid
14850397Sobrienstringpool_statistics ()
14950397Sobrien{
15050397Sobrien  ht_dump_statistics (ident_hash);
15150397Sobrien}
15250397Sobrien
15350397Sobrien/* Mark an identifier for GC.  */
15450397Sobrien
15550397Sobrienstatic int
15650397Sobrienmark_ident (pfile, h, v)
15750397Sobrien     struct cpp_reader *pfile ATTRIBUTE_UNUSED;
15850397Sobrien     hashnode h;
15950397Sobrien     const PTR v ATTRIBUTE_UNUSED;
16050397Sobrien{
16150397Sobrien  ggc_mark_tree (HT_IDENT_TO_GCC_IDENT (h));
16250397Sobrien  return 1;
16350397Sobrien}
16450397Sobrien
16550397Sobrien/* Mark all identifiers for GC.  */
16650397Sobrien
16750397Sobrienstatic void
16850397Sobrienmark_ident_hash (arg)
16950397Sobrien     PTR arg ATTRIBUTE_UNUSED;
17050397Sobrien{
17150397Sobrien  ht_forall (ident_hash, mark_ident, NULL);
17250397Sobrien}
17350397Sobrien