]>
Commit | Line | Data |
---|---|---|
520a57c8 | 1 | /* String pool for GCC. |
2a967f3d | 2 | Copyright (C) 2000, 2001 Free Software Foundation, Inc. |
520a57c8 | 3 | |
1322177d | 4 | This file is part of GCC. |
520a57c8 | 5 | |
1322177d LB |
6 | GCC is free software; you can redistribute it and/or modify it under |
7 | the terms of the GNU General Public License as published by the Free | |
8 | Software Foundation; either version 2, or (at your option) any later | |
9 | version. | |
520a57c8 | 10 | |
1322177d LB |
11 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
12 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
520a57c8 ZW |
13 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
14 | for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
1322177d | 17 | along with GCC; see the file COPYING. If not, write to the Free |
520a57c8 ZW |
18 | Software Foundation, 59 Temple Place - Suite 330, Boston, MA |
19 | 02111-1307, USA. */ | |
20 | ||
ff7cc307 | 21 | /* String text, identifier text and identifier node allocator. Strings |
2a967f3d NB |
22 | allocated by ggc_alloc_string are stored in an obstack which is |
23 | never shrunk. Identifiers are uniquely stored in a hash table. | |
520a57c8 | 24 | |
2a967f3d NB |
25 | We have our own private hash table implementation. libiberty's |
26 | hashtab.c is not used because it requires 100% average space | |
27 | overhead per string, which is unacceptable. Also, this algorithm | |
28 | is faster. */ | |
520a57c8 ZW |
29 | |
30 | #include "config.h" | |
31 | #include "system.h" | |
32 | #include "ggc.h" | |
33 | #include "tree.h" | |
2a967f3d | 34 | #include "hashtable.h" |
520a57c8 ZW |
35 | |
36 | /* The "" allocated string. */ | |
37 | const char empty_string[] = ""; | |
38 | ||
a8a05998 ZW |
39 | /* Character strings, each containing a single decimal digit. |
40 | Written this way to save space. */ | |
41 | const char digit_vector[] = { | |
42 | '0', 0, '1', 0, '2', 0, '3', 0, '4', 0, | |
43 | '5', 0, '6', 0, '7', 0, '8', 0, '9', 0 | |
44 | }; | |
45 | ||
2a967f3d | 46 | struct ht *ident_hash; |
520a57c8 | 47 | static struct obstack string_stack; |
520a57c8 | 48 | |
2a967f3d NB |
49 | static hashnode alloc_node PARAMS ((hash_table *)); |
50 | static int mark_ident PARAMS ((struct cpp_reader *, hashnode, const PTR)); | |
51 | static void mark_ident_hash PARAMS ((void *)); | |
2a967f3d | 52 | |
520a57c8 ZW |
53 | /* Initialize the string pool. */ |
54 | void | |
55 | init_stringpool () | |
56 | { | |
2a967f3d NB |
57 | /* Create with 16K (2^14) entries. */ |
58 | ident_hash = ht_create (14); | |
59 | ident_hash->alloc_node = alloc_node; | |
520a57c8 | 60 | gcc_obstack_init (&string_stack); |
2a967f3d | 61 | ggc_add_root (&ident_hash, 1, sizeof ident_hash, mark_ident_hash); |
520a57c8 ZW |
62 | } |
63 | ||
2a967f3d NB |
64 | /* Allocate a hash node. */ |
65 | static hashnode | |
66 | alloc_node (table) | |
67 | hash_table *table ATTRIBUTE_UNUSED; | |
520a57c8 | 68 | { |
2a967f3d | 69 | return GCC_IDENT_TO_HT_IDENT (make_node (IDENTIFIER_NODE)); |
520a57c8 ZW |
70 | } |
71 | ||
72 | /* Allocate and return a string constant of length LENGTH, containing | |
73 | CONTENTS. If LENGTH is -1, CONTENTS is assumed to be a | |
74 | nul-terminated string, and the length is calculated using strlen. | |
75 | If the same string constant has been allocated before, that copy is | |
76 | returned this time too. */ | |
77 | ||
78 | const char * | |
79 | ggc_alloc_string (contents, length) | |
80 | const char *contents; | |
81 | int length; | |
82 | { | |
520a57c8 ZW |
83 | if (length == -1) |
84 | length = strlen (contents); | |
85 | ||
86 | if (length == 0) | |
87 | return empty_string; | |
0df6c2c7 | 88 | if (length == 1 && ISDIGIT (contents[0])) |
a8a05998 | 89 | return digit_string (contents[0] - '0'); |
520a57c8 | 90 | |
4c521bad NB |
91 | obstack_grow0 (&string_stack, contents, length); |
92 | return obstack_finish (&string_stack); | |
520a57c8 ZW |
93 | } |
94 | ||
95 | /* Return an IDENTIFIER_NODE whose name is TEXT (a null-terminated string). | |
96 | If an identifier with that name has previously been referred to, | |
97 | the same node is returned this time. */ | |
2a967f3d | 98 | |
520a57c8 ZW |
99 | tree |
100 | get_identifier (text) | |
101 | const char *text; | |
102 | { | |
2a967f3d NB |
103 | hashnode ht_node = ht_lookup (ident_hash, |
104 | (const unsigned char *) text, | |
105 | strlen (text), HT_ALLOC); | |
4c521bad | 106 | |
2a967f3d NB |
107 | /* ht_node can't be NULL here. */ |
108 | return HT_IDENT_TO_GCC_IDENT (ht_node); | |
520a57c8 ZW |
109 | } |
110 | ||
4bad9e39 APB |
111 | /* Identical to get_identifier, except that the length is assumed |
112 | known. */ | |
786de7eb | 113 | |
4bad9e39 APB |
114 | tree |
115 | get_identifier_with_length (text, length) | |
116 | const char *text; | |
117 | unsigned int length; | |
118 | { | |
119 | hashnode ht_node = ht_lookup (ident_hash, | |
120 | (const unsigned char *) text, | |
121 | length, HT_ALLOC); | |
122 | ||
123 | /* ht_node can't be NULL here. */ | |
124 | return HT_IDENT_TO_GCC_IDENT (ht_node); | |
125 | } | |
126 | ||
520a57c8 ZW |
127 | /* If an identifier with the name TEXT (a null-terminated string) has |
128 | previously been referred to, return that node; otherwise return | |
129 | NULL_TREE. */ | |
130 | ||
131 | tree | |
132 | maybe_get_identifier (text) | |
133 | const char *text; | |
134 | { | |
2a967f3d | 135 | hashnode ht_node; |
520a57c8 | 136 | |
2a967f3d | 137 | ht_node = ht_lookup (ident_hash, (const unsigned char *) text, |
083e9f92 | 138 | strlen (text), HT_NO_INSERT); |
2a967f3d | 139 | if (ht_node) |
083e9f92 | 140 | return HT_IDENT_TO_GCC_IDENT (ht_node); |
520a57c8 | 141 | |
4c521bad | 142 | return NULL_TREE; |
71b7be38 ZW |
143 | } |
144 | ||
520a57c8 ZW |
145 | /* Report some basic statistics about the string pool. */ |
146 | ||
147 | void | |
148 | stringpool_statistics () | |
149 | { | |
2a967f3d | 150 | ht_dump_statistics (ident_hash); |
520a57c8 ZW |
151 | } |
152 | ||
2a967f3d | 153 | /* Mark an identifier for GC. */ |
520a57c8 | 154 | |
2a967f3d NB |
155 | static int |
156 | mark_ident (pfile, h, v) | |
157 | struct cpp_reader *pfile ATTRIBUTE_UNUSED; | |
158 | hashnode h; | |
159 | const PTR v ATTRIBUTE_UNUSED; | |
520a57c8 | 160 | { |
2a967f3d NB |
161 | ggc_mark_nonnull_tree (HT_IDENT_TO_GCC_IDENT (h)); |
162 | return 1; | |
163 | } | |
520a57c8 | 164 | |
2a967f3d NB |
165 | /* Mark all identifiers for GC. */ |
166 | ||
167 | static void | |
168 | mark_ident_hash (arg) | |
169 | PTR arg ATTRIBUTE_UNUSED; | |
170 | { | |
171 | ht_forall (ident_hash, mark_ident, NULL); | |
520a57c8 | 172 | } |