OSDN Git Service

* Makefile.in (OBJS, LIBCPP_OBJS, LIBCPP_DEPS,
[pf3gnuchains/gcc-fork.git] / gcc / stringpool.c
1 /* String pool for GCC.
2    Copyright (C) 2000, 2001 Free Software Foundation, Inc.
3
4 This file is part of GNU CC.
5
6 GNU CC is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10
11 GNU CC is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
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
17 along with GNU CC; see the file COPYING.  If not, write to the Free
18 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA.  */
20
21 /* String text, identifer text and identifier node allocator.  Strings
22    allocated by ggc_alloc_string are stored in an obstack which is
23    never shrunk.  Identifiers are uniquely stored in a hash table.
24
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.  */
29
30 #include "config.h"
31 #include "system.h"
32 #include "ggc.h"
33 #include "tree.h"
34 #include "hashtable.h"
35 #include "flags.h"
36 #include "toplev.h"
37
38 #define IS_FE_IDENT(NODE) (TREE_CODE (NODE) == IDENTIFIER_NODE)
39
40 /* The "" allocated string.  */
41 const char empty_string[] = "";
42
43 /* Character strings, each containing a single decimal digit.
44    Written this way to save space.  */
45 const char digit_vector[] = {
46   '0', 0, '1', 0, '2', 0, '3', 0, '4', 0,
47   '5', 0, '6', 0, '7', 0, '8', 0, '9', 0
48 };
49
50 struct ht *ident_hash;
51 static struct obstack string_stack;
52 static int do_identifier_warnings;
53
54 static hashnode alloc_node PARAMS ((hash_table *));
55 static int mark_ident PARAMS ((struct cpp_reader *, hashnode, const PTR));
56 static void mark_ident_hash PARAMS ((void *));
57 static int scan_for_clashes PARAMS ((struct cpp_reader *, hashnode,
58                                      const char *));
59
60 /* Initialize the string pool.  */
61 void
62 init_stringpool ()
63 {
64   /* Create with 16K (2^14) entries.  */
65   ident_hash = ht_create (14);
66   ident_hash->alloc_node = alloc_node;
67   gcc_obstack_init (&string_stack);
68   ggc_add_root (&ident_hash, 1, sizeof ident_hash, mark_ident_hash);
69 }
70
71 /* Allocate a hash node.  */
72 static hashnode
73 alloc_node (table)
74      hash_table *table ATTRIBUTE_UNUSED;
75 {
76   return GCC_IDENT_TO_HT_IDENT (make_node (IDENTIFIER_NODE));
77 }
78
79 /* Allocate and return a string constant of length LENGTH, containing
80    CONTENTS.  If LENGTH is -1, CONTENTS is assumed to be a
81    nul-terminated string, and the length is calculated using strlen.
82    If the same string constant has been allocated before, that copy is
83    returned this time too.  */
84
85 const char *
86 ggc_alloc_string (contents, length)
87      const char *contents;
88      int length;
89 {
90   if (length == -1)
91     length = strlen (contents);
92
93   if (length == 0)
94     return empty_string;
95   if (length == 1 && contents[0] >= '0' && contents[0] <= '9')
96     return digit_string (contents[0] - '0');
97
98   obstack_grow0 (&string_stack, contents, length);
99   return obstack_finish (&string_stack);
100 }
101
102 /* NODE is an identifier known to the preprocessor.  Make it known to
103    the front ends as well.  */
104
105 void
106 make_identifier (node)
107      tree node;
108 {
109   /* If this identifier is longer than the clash-warning length,
110      do a brute force search of the entire table for clashes.  */
111   if (warn_id_clash && do_identifier_warnings
112       && IDENTIFIER_LENGTH (node) >= id_clash_len)
113     ht_forall (ident_hash, (ht_cb) scan_for_clashes,
114                IDENTIFIER_POINTER (node));
115
116   TREE_SET_CODE (node, IDENTIFIER_NODE);
117 #ifdef GATHER_STATISTICS
118   id_string_size += IDENTIFIER_LENGTH (node);
119 #endif
120 }
121
122 /* Return an IDENTIFIER_NODE whose name is TEXT (a null-terminated string).
123    If an identifier with that name has previously been referred to,
124    the same node is returned this time.  */
125
126 tree
127 get_identifier (text)
128      const char *text;
129 {
130   hashnode ht_node = ht_lookup (ident_hash,
131                                 (const unsigned char *) text,
132                                 strlen (text), HT_ALLOC);
133
134   /* ht_node can't be NULL here.  */
135   return HT_IDENT_TO_GCC_IDENT (ht_node);
136 }
137
138 /* If an identifier with the name TEXT (a null-terminated string) has
139    previously been referred to, return that node; otherwise return
140    NULL_TREE.  */
141
142 tree
143 maybe_get_identifier (text)
144      const char *text;
145 {
146   hashnode ht_node;
147   tree node;
148   size_t length = strlen (text);
149
150   ht_node = ht_lookup (ident_hash, (const unsigned char *) text,
151                        length, HT_NO_INSERT);
152   if (ht_node)
153     {
154       node = HT_IDENT_TO_GCC_IDENT (ht_node);
155       if (IS_FE_IDENT (node))
156         return node;
157     }
158
159   return NULL_TREE;
160 }
161
162 /* If this identifier is longer than the clash-warning length,
163    do a brute force search of the entire table for clashes.  */
164
165 static int
166 scan_for_clashes (pfile, h, text)
167      struct cpp_reader *pfile ATTRIBUTE_UNUSED;
168      hashnode h;
169      const char *text;
170 {
171   tree node = HT_IDENT_TO_GCC_IDENT (h);
172
173   if (IS_FE_IDENT (node)
174       && IDENTIFIER_LENGTH (node) >= id_clash_len
175       && !memcmp (IDENTIFIER_POINTER (node), text, id_clash_len))
176     {
177       warning ("\"%s\" and \"%s\" identical in first %d characters",
178                text, IDENTIFIER_POINTER (node), id_clash_len);
179       return 0;
180     }
181
182   return 1;
183 }
184
185 /* Record the size of an identifier node for the language in use.
186    SIZE is the total size in bytes.
187    This is called by the language-specific files.  This must be
188    called before allocating any identifiers.  */
189
190 void
191 set_identifier_size (size)
192      int size;
193 {
194   tree_code_length[(int) IDENTIFIER_NODE]
195     = (size - sizeof (struct tree_common)) / sizeof (tree);
196 }
197
198 /* Enable warnings on similar identifiers (if requested).
199    Done after the built-in identifiers are created.  */
200
201 void
202 start_identifier_warnings ()
203 {
204   do_identifier_warnings = 1;
205 }
206
207 /* Report some basic statistics about the string pool.  */
208
209 void
210 stringpool_statistics ()
211 {
212   ht_dump_statistics (ident_hash);
213 }
214
215 /* Mark an identifier for GC.  */
216
217 static int
218 mark_ident (pfile, h, v)
219      struct cpp_reader *pfile ATTRIBUTE_UNUSED;
220      hashnode h;
221      const PTR v ATTRIBUTE_UNUSED;
222 {
223   ggc_mark_nonnull_tree (HT_IDENT_TO_GCC_IDENT (h));
224   return 1;
225 }
226
227 /* Mark all identifiers for GC.  */
228
229 static void
230 mark_ident_hash (arg)
231      PTR arg ATTRIBUTE_UNUSED;
232 {
233   ht_forall (ident_hash, mark_ident, NULL);
234 }