xref: /dragonfly/contrib/gcc-8.0/gcc/stringpool.c (revision 38fd1498)
1*38fd1498Szrj /* String pool for GCC.
2*38fd1498Szrj    Copyright (C) 2000-2018 Free Software Foundation, Inc.
3*38fd1498Szrj 
4*38fd1498Szrj This file is part of GCC.
5*38fd1498Szrj 
6*38fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
7*38fd1498Szrj the terms of the GNU General Public License as published by the Free
8*38fd1498Szrj Software Foundation; either version 3, or (at your option) any later
9*38fd1498Szrj version.
10*38fd1498Szrj 
11*38fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12*38fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
13*38fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14*38fd1498Szrj for more details.
15*38fd1498Szrj 
16*38fd1498Szrj You should have received a copy of the GNU General Public License
17*38fd1498Szrj along with GCC; see the file COPYING3.  If not see
18*38fd1498Szrj <http://www.gnu.org/licenses/>.  */
19*38fd1498Szrj 
20*38fd1498Szrj /* String text, identifier text and identifier node allocator.
21*38fd1498Szrj    Identifiers are uniquely stored in a hash table.
22*38fd1498Szrj 
23*38fd1498Szrj    We use cpplib's hash table implementation.  libiberty's
24*38fd1498Szrj    hashtab.c is not used because it requires 100% average space
25*38fd1498Szrj    overhead per string, which is unacceptable.  Also, this algorithm
26*38fd1498Szrj    is faster.  */
27*38fd1498Szrj 
28*38fd1498Szrj #include "config.h"
29*38fd1498Szrj #include "system.h"
30*38fd1498Szrj #include "coretypes.h"
31*38fd1498Szrj #include "tree.h"
32*38fd1498Szrj 
33*38fd1498Szrj struct ht *ident_hash;
34*38fd1498Szrj 
35*38fd1498Szrj static hashnode alloc_node (cpp_hash_table *);
36*38fd1498Szrj static int mark_ident (struct cpp_reader *, hashnode, const void *);
37*38fd1498Szrj 
38*38fd1498Szrj static void *
stringpool_ggc_alloc(size_t x)39*38fd1498Szrj stringpool_ggc_alloc (size_t x)
40*38fd1498Szrj {
41*38fd1498Szrj   return ggc_alloc_atomic (x);
42*38fd1498Szrj }
43*38fd1498Szrj 
44*38fd1498Szrj /* Initialize the string pool.  */
45*38fd1498Szrj void
init_stringpool(void)46*38fd1498Szrj init_stringpool (void)
47*38fd1498Szrj {
48*38fd1498Szrj   /* Clean up if we're called more than once.
49*38fd1498Szrj      (We can't make this idempotent since identifiers contain state) */
50*38fd1498Szrj   if (ident_hash)
51*38fd1498Szrj     ht_destroy (ident_hash);
52*38fd1498Szrj 
53*38fd1498Szrj   /* Create with 16K (2^14) entries.  */
54*38fd1498Szrj   ident_hash = ht_create (14);
55*38fd1498Szrj   ident_hash->alloc_node = alloc_node;
56*38fd1498Szrj   ident_hash->alloc_subobject = stringpool_ggc_alloc;
57*38fd1498Szrj }
58*38fd1498Szrj 
59*38fd1498Szrj /* Allocate a hash node.  */
60*38fd1498Szrj static hashnode
alloc_node(cpp_hash_table * table ATTRIBUTE_UNUSED)61*38fd1498Szrj alloc_node (cpp_hash_table *table ATTRIBUTE_UNUSED)
62*38fd1498Szrj {
63*38fd1498Szrj   return GCC_IDENT_TO_HT_IDENT (make_node (IDENTIFIER_NODE));
64*38fd1498Szrj }
65*38fd1498Szrj 
66*38fd1498Szrj /* Allocate and return a string constant of length LENGTH, containing
67*38fd1498Szrj    CONTENTS.  If LENGTH is -1, CONTENTS is assumed to be a
68*38fd1498Szrj    nul-terminated string, and the length is calculated using strlen.  */
69*38fd1498Szrj 
70*38fd1498Szrj const char *
ggc_alloc_string(const char * contents,int length MEM_STAT_DECL)71*38fd1498Szrj ggc_alloc_string (const char *contents, int length MEM_STAT_DECL)
72*38fd1498Szrj {
73*38fd1498Szrj   if (length == -1)
74*38fd1498Szrj     length = strlen (contents);
75*38fd1498Szrj 
76*38fd1498Szrj   if (!length)
77*38fd1498Szrj     return "";
78*38fd1498Szrj 
79*38fd1498Szrj   char *result = (char *) ggc_alloc_atomic (length + 1);
80*38fd1498Szrj   memcpy (result, contents, length);
81*38fd1498Szrj   result[length] = '\0';
82*38fd1498Szrj 
83*38fd1498Szrj   return (const char *) result;
84*38fd1498Szrj }
85*38fd1498Szrj 
86*38fd1498Szrj /* Return an IDENTIFIER_NODE whose name is TEXT (a null-terminated string).
87*38fd1498Szrj    If an identifier with that name has previously been referred to,
88*38fd1498Szrj    the same node is returned this time.  */
89*38fd1498Szrj 
90*38fd1498Szrj #undef get_identifier
91*38fd1498Szrj 
92*38fd1498Szrj tree
get_identifier(const char * text)93*38fd1498Szrj get_identifier (const char *text)
94*38fd1498Szrj {
95*38fd1498Szrj   hashnode ht_node = ht_lookup (ident_hash,
96*38fd1498Szrj 				(const unsigned char *) text,
97*38fd1498Szrj 				strlen (text), HT_ALLOC);
98*38fd1498Szrj 
99*38fd1498Szrj   /* ht_node can't be NULL here.  */
100*38fd1498Szrj   return HT_IDENT_TO_GCC_IDENT (ht_node);
101*38fd1498Szrj }
102*38fd1498Szrj 
103*38fd1498Szrj /* Identical to get_identifier, except that the length is assumed
104*38fd1498Szrj    known.  */
105*38fd1498Szrj 
106*38fd1498Szrj tree
get_identifier_with_length(const char * text,size_t length)107*38fd1498Szrj get_identifier_with_length (const char *text, size_t length)
108*38fd1498Szrj {
109*38fd1498Szrj   hashnode ht_node = ht_lookup (ident_hash,
110*38fd1498Szrj 				(const unsigned char *) text,
111*38fd1498Szrj 				length, HT_ALLOC);
112*38fd1498Szrj 
113*38fd1498Szrj   /* ht_node can't be NULL here.  */
114*38fd1498Szrj   return HT_IDENT_TO_GCC_IDENT (ht_node);
115*38fd1498Szrj }
116*38fd1498Szrj 
117*38fd1498Szrj /* If an identifier with the name TEXT (a null-terminated string) has
118*38fd1498Szrj    previously been referred to, return that node; otherwise return
119*38fd1498Szrj    NULL_TREE.  */
120*38fd1498Szrj 
121*38fd1498Szrj tree
maybe_get_identifier(const char * text)122*38fd1498Szrj maybe_get_identifier (const char *text)
123*38fd1498Szrj {
124*38fd1498Szrj   hashnode ht_node;
125*38fd1498Szrj 
126*38fd1498Szrj   ht_node = ht_lookup (ident_hash, (const unsigned char *) text,
127*38fd1498Szrj 		       strlen (text), HT_NO_INSERT);
128*38fd1498Szrj   if (ht_node)
129*38fd1498Szrj     return HT_IDENT_TO_GCC_IDENT (ht_node);
130*38fd1498Szrj 
131*38fd1498Szrj   return NULL_TREE;
132*38fd1498Szrj }
133*38fd1498Szrj 
134*38fd1498Szrj /* Report some basic statistics about the string pool.  */
135*38fd1498Szrj 
136*38fd1498Szrj void
stringpool_statistics(void)137*38fd1498Szrj stringpool_statistics (void)
138*38fd1498Szrj {
139*38fd1498Szrj   ht_dump_statistics (ident_hash);
140*38fd1498Szrj }
141*38fd1498Szrj 
142*38fd1498Szrj /* Mark an identifier for GC.  */
143*38fd1498Szrj 
144*38fd1498Szrj static int
mark_ident(struct cpp_reader * pfile ATTRIBUTE_UNUSED,hashnode h,const void * v ATTRIBUTE_UNUSED)145*38fd1498Szrj mark_ident (struct cpp_reader *pfile ATTRIBUTE_UNUSED, hashnode h,
146*38fd1498Szrj 	    const void *v ATTRIBUTE_UNUSED)
147*38fd1498Szrj {
148*38fd1498Szrj   gt_ggc_m_9tree_node (HT_IDENT_TO_GCC_IDENT (h));
149*38fd1498Szrj   return 1;
150*38fd1498Szrj }
151*38fd1498Szrj 
152*38fd1498Szrj /* Return true if an identifier should be removed from the table.  */
153*38fd1498Szrj 
154*38fd1498Szrj static int
maybe_delete_ident(struct cpp_reader * pfile ATTRIBUTE_UNUSED,hashnode h,const void * v ATTRIBUTE_UNUSED)155*38fd1498Szrj maybe_delete_ident (struct cpp_reader *pfile ATTRIBUTE_UNUSED, hashnode h,
156*38fd1498Szrj 		    const void *v ATTRIBUTE_UNUSED)
157*38fd1498Szrj {
158*38fd1498Szrj   return !ggc_marked_p (HT_IDENT_TO_GCC_IDENT (h));
159*38fd1498Szrj }
160*38fd1498Szrj 
161*38fd1498Szrj /* Mark the trees hanging off the identifier node for GGC.  These are
162*38fd1498Szrj    handled specially (not using gengtype) because identifiers are only
163*38fd1498Szrj    roots during one part of compilation.  */
164*38fd1498Szrj 
165*38fd1498Szrj void
ggc_mark_stringpool(void)166*38fd1498Szrj ggc_mark_stringpool (void)
167*38fd1498Szrj {
168*38fd1498Szrj   ht_forall (ident_hash, mark_ident, NULL);
169*38fd1498Szrj }
170*38fd1498Szrj 
171*38fd1498Szrj /* Purge the identifier hash of identifiers which are no longer
172*38fd1498Szrj    referenced.  */
173*38fd1498Szrj 
174*38fd1498Szrj void
ggc_purge_stringpool(void)175*38fd1498Szrj ggc_purge_stringpool (void)
176*38fd1498Szrj {
177*38fd1498Szrj   ht_purge (ident_hash, maybe_delete_ident, NULL);
178*38fd1498Szrj }
179*38fd1498Szrj 
180*38fd1498Szrj /* Pointer-walking routine for strings (not very interesting, since
181*38fd1498Szrj    strings don't contain pointers).  */
182*38fd1498Szrj 
183*38fd1498Szrj void
gt_pch_p_S(void * obj ATTRIBUTE_UNUSED,void * x ATTRIBUTE_UNUSED,gt_pointer_operator op ATTRIBUTE_UNUSED,void * cookie ATTRIBUTE_UNUSED)184*38fd1498Szrj gt_pch_p_S (void *obj ATTRIBUTE_UNUSED, void *x ATTRIBUTE_UNUSED,
185*38fd1498Szrj 	    gt_pointer_operator op ATTRIBUTE_UNUSED,
186*38fd1498Szrj 	    void *cookie ATTRIBUTE_UNUSED)
187*38fd1498Szrj {
188*38fd1498Szrj }
189*38fd1498Szrj 
190*38fd1498Szrj /* PCH pointer-walking routine for strings.  */
191*38fd1498Szrj 
192*38fd1498Szrj void
gt_pch_n_S(const void * x)193*38fd1498Szrj gt_pch_n_S (const void *x)
194*38fd1498Szrj {
195*38fd1498Szrj   gt_pch_note_object (CONST_CAST (void *, x), CONST_CAST (void *, x),
196*38fd1498Szrj 		      &gt_pch_p_S);
197*38fd1498Szrj }
198*38fd1498Szrj 
199*38fd1498Szrj 
200*38fd1498Szrj /* User-callable entry point for marking string X.  */
201*38fd1498Szrj 
202*38fd1498Szrj void
gt_pch_nx(const char * & x)203*38fd1498Szrj gt_pch_nx (const char *& x)
204*38fd1498Szrj {
205*38fd1498Szrj   gt_pch_n_S (x);
206*38fd1498Szrj }
207*38fd1498Szrj 
208*38fd1498Szrj void
gt_pch_nx(unsigned char * & x)209*38fd1498Szrj gt_pch_nx (unsigned char *& x)
210*38fd1498Szrj {
211*38fd1498Szrj   gt_pch_n_S (x);
212*38fd1498Szrj }
213*38fd1498Szrj 
214*38fd1498Szrj void
gt_pch_nx(unsigned char & x ATTRIBUTE_UNUSED)215*38fd1498Szrj gt_pch_nx (unsigned char& x ATTRIBUTE_UNUSED)
216*38fd1498Szrj {
217*38fd1498Szrj }
218*38fd1498Szrj 
219*38fd1498Szrj void
gt_pch_nx(unsigned char * x,gt_pointer_operator op,void * cookie)220*38fd1498Szrj gt_pch_nx (unsigned char *x, gt_pointer_operator op, void *cookie)
221*38fd1498Szrj {
222*38fd1498Szrj   op (x, cookie);
223*38fd1498Szrj }
224*38fd1498Szrj 
225*38fd1498Szrj /* Handle saving and restoring the string pool for PCH.  */
226*38fd1498Szrj 
227*38fd1498Szrj /* SPD is saved in the PCH file and holds the information needed
228*38fd1498Szrj    to restore the string pool.  */
229*38fd1498Szrj 
230*38fd1498Szrj struct GTY(()) string_pool_data {
231*38fd1498Szrj   ht_identifier_ptr *
232*38fd1498Szrj     GTY((length ("%h.nslots"),
233*38fd1498Szrj 	 nested_ptr (union tree_node, "%h ? GCC_IDENT_TO_HT_IDENT (%h) : NULL",
234*38fd1498Szrj 		     "%h ? HT_IDENT_TO_GCC_IDENT (%h) : NULL")))
235*38fd1498Szrj     entries;
236*38fd1498Szrj   unsigned int nslots;
237*38fd1498Szrj   unsigned int nelements;
238*38fd1498Szrj };
239*38fd1498Szrj 
240*38fd1498Szrj static GTY(()) struct string_pool_data * spd;
241*38fd1498Szrj 
242*38fd1498Szrj /* Save the stringpool data in SPD.  */
243*38fd1498Szrj 
244*38fd1498Szrj void
gt_pch_save_stringpool(void)245*38fd1498Szrj gt_pch_save_stringpool (void)
246*38fd1498Szrj {
247*38fd1498Szrj   spd = ggc_alloc<string_pool_data> ();
248*38fd1498Szrj   spd->nslots = ident_hash->nslots;
249*38fd1498Szrj   spd->nelements = ident_hash->nelements;
250*38fd1498Szrj   spd->entries = ggc_vec_alloc<ht_identifier_ptr> (spd->nslots);
251*38fd1498Szrj   memcpy (spd->entries, ident_hash->entries,
252*38fd1498Szrj 	  spd->nslots * sizeof (spd->entries[0]));
253*38fd1498Szrj }
254*38fd1498Szrj 
255*38fd1498Szrj /* Return the stringpool to its state before gt_pch_save_stringpool
256*38fd1498Szrj    was called.  */
257*38fd1498Szrj 
258*38fd1498Szrj void
gt_pch_fixup_stringpool(void)259*38fd1498Szrj gt_pch_fixup_stringpool (void)
260*38fd1498Szrj {
261*38fd1498Szrj }
262*38fd1498Szrj 
263*38fd1498Szrj /* A PCH file has been restored, which loaded SPD; fill the real hash table
264*38fd1498Szrj    from SPD.  */
265*38fd1498Szrj 
266*38fd1498Szrj void
gt_pch_restore_stringpool(void)267*38fd1498Szrj gt_pch_restore_stringpool (void)
268*38fd1498Szrj {
269*38fd1498Szrj   ht_load (ident_hash, spd->entries, spd->nslots, spd->nelements, false);
270*38fd1498Szrj   spd = NULL;
271*38fd1498Szrj }
272*38fd1498Szrj 
273*38fd1498Szrj #include "gt-stringpool.h"
274