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