11debfc3dSmrg /* String pool for GCC.
2*8feb0f0bSmrg Copyright (C) 2000-2020 Free Software Foundation, Inc.
31debfc3dSmrg
41debfc3dSmrg This file is part of GCC.
51debfc3dSmrg
61debfc3dSmrg GCC is free software; you can redistribute it and/or modify it under
71debfc3dSmrg the terms of the GNU General Public License as published by the Free
81debfc3dSmrg Software Foundation; either version 3, or (at your option) any later
91debfc3dSmrg version.
101debfc3dSmrg
111debfc3dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
121debfc3dSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
131debfc3dSmrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
141debfc3dSmrg for more details.
151debfc3dSmrg
161debfc3dSmrg You should have received a copy of the GNU General Public License
171debfc3dSmrg along with GCC; see the file COPYING3. If not see
181debfc3dSmrg <http://www.gnu.org/licenses/>. */
191debfc3dSmrg
201debfc3dSmrg /* String text, identifier text and identifier node allocator.
211debfc3dSmrg Identifiers are uniquely stored in a hash table.
221debfc3dSmrg
231debfc3dSmrg We use cpplib's hash table implementation. libiberty's
241debfc3dSmrg hashtab.c is not used because it requires 100% average space
251debfc3dSmrg overhead per string, which is unacceptable. Also, this algorithm
261debfc3dSmrg is faster. */
271debfc3dSmrg
281debfc3dSmrg #include "config.h"
291debfc3dSmrg #include "system.h"
301debfc3dSmrg #include "coretypes.h"
311debfc3dSmrg #include "tree.h"
321debfc3dSmrg
331debfc3dSmrg struct ht *ident_hash;
341debfc3dSmrg
351debfc3dSmrg static hashnode alloc_node (cpp_hash_table *);
361debfc3dSmrg static int mark_ident (struct cpp_reader *, hashnode, const void *);
371debfc3dSmrg
381debfc3dSmrg static void *
stringpool_ggc_alloc(size_t x)391debfc3dSmrg stringpool_ggc_alloc (size_t x)
401debfc3dSmrg {
411debfc3dSmrg return ggc_alloc_atomic (x);
421debfc3dSmrg }
431debfc3dSmrg
441debfc3dSmrg /* Initialize the string pool. */
451debfc3dSmrg void
init_stringpool(void)461debfc3dSmrg init_stringpool (void)
471debfc3dSmrg {
481debfc3dSmrg /* Clean up if we're called more than once.
491debfc3dSmrg (We can't make this idempotent since identifiers contain state) */
501debfc3dSmrg if (ident_hash)
511debfc3dSmrg ht_destroy (ident_hash);
521debfc3dSmrg
531debfc3dSmrg /* Create with 16K (2^14) entries. */
541debfc3dSmrg ident_hash = ht_create (14);
551debfc3dSmrg ident_hash->alloc_node = alloc_node;
561debfc3dSmrg ident_hash->alloc_subobject = stringpool_ggc_alloc;
571debfc3dSmrg }
581debfc3dSmrg
591debfc3dSmrg /* Allocate a hash node. */
601debfc3dSmrg static hashnode
alloc_node(cpp_hash_table * table ATTRIBUTE_UNUSED)611debfc3dSmrg alloc_node (cpp_hash_table *table ATTRIBUTE_UNUSED)
621debfc3dSmrg {
631debfc3dSmrg return GCC_IDENT_TO_HT_IDENT (make_node (IDENTIFIER_NODE));
641debfc3dSmrg }
651debfc3dSmrg
661debfc3dSmrg /* Allocate and return a string constant of length LENGTH, containing
671debfc3dSmrg CONTENTS. If LENGTH is -1, CONTENTS is assumed to be a
681debfc3dSmrg nul-terminated string, and the length is calculated using strlen. */
691debfc3dSmrg
701debfc3dSmrg const char *
ggc_alloc_string(const char * contents,int length MEM_STAT_DECL)711debfc3dSmrg ggc_alloc_string (const char *contents, int length MEM_STAT_DECL)
721debfc3dSmrg {
731debfc3dSmrg if (length == -1)
741debfc3dSmrg length = strlen (contents);
751debfc3dSmrg
76a2dc1f3fSmrg if (!length)
77a2dc1f3fSmrg return "";
781debfc3dSmrg
79a2dc1f3fSmrg char *result = (char *) ggc_alloc_atomic (length + 1);
801debfc3dSmrg memcpy (result, contents, length);
811debfc3dSmrg result[length] = '\0';
82a2dc1f3fSmrg
831debfc3dSmrg return (const char *) result;
841debfc3dSmrg }
851debfc3dSmrg
861debfc3dSmrg /* Return an IDENTIFIER_NODE whose name is TEXT (a null-terminated string).
871debfc3dSmrg If an identifier with that name has previously been referred to,
881debfc3dSmrg the same node is returned this time. */
891debfc3dSmrg
901debfc3dSmrg #undef get_identifier
911debfc3dSmrg
921debfc3dSmrg tree
get_identifier(const char * text)931debfc3dSmrg get_identifier (const char *text)
941debfc3dSmrg {
951debfc3dSmrg hashnode ht_node = ht_lookup (ident_hash,
961debfc3dSmrg (const unsigned char *) text,
971debfc3dSmrg strlen (text), HT_ALLOC);
981debfc3dSmrg
991debfc3dSmrg /* ht_node can't be NULL here. */
1001debfc3dSmrg return HT_IDENT_TO_GCC_IDENT (ht_node);
1011debfc3dSmrg }
1021debfc3dSmrg
1031debfc3dSmrg /* Identical to get_identifier, except that the length is assumed
1041debfc3dSmrg known. */
1051debfc3dSmrg
1061debfc3dSmrg tree
get_identifier_with_length(const char * text,size_t length)1071debfc3dSmrg get_identifier_with_length (const char *text, size_t length)
1081debfc3dSmrg {
1091debfc3dSmrg hashnode ht_node = ht_lookup (ident_hash,
1101debfc3dSmrg (const unsigned char *) text,
1111debfc3dSmrg length, HT_ALLOC);
1121debfc3dSmrg
1131debfc3dSmrg /* ht_node can't be NULL here. */
1141debfc3dSmrg return HT_IDENT_TO_GCC_IDENT (ht_node);
1151debfc3dSmrg }
1161debfc3dSmrg
1171debfc3dSmrg /* If an identifier with the name TEXT (a null-terminated string) has
1181debfc3dSmrg previously been referred to, return that node; otherwise return
1191debfc3dSmrg NULL_TREE. */
1201debfc3dSmrg
1211debfc3dSmrg tree
maybe_get_identifier(const char * text)1221debfc3dSmrg maybe_get_identifier (const char *text)
1231debfc3dSmrg {
1241debfc3dSmrg hashnode ht_node;
1251debfc3dSmrg
1261debfc3dSmrg ht_node = ht_lookup (ident_hash, (const unsigned char *) text,
1271debfc3dSmrg strlen (text), HT_NO_INSERT);
1281debfc3dSmrg if (ht_node)
1291debfc3dSmrg return HT_IDENT_TO_GCC_IDENT (ht_node);
1301debfc3dSmrg
1311debfc3dSmrg return NULL_TREE;
1321debfc3dSmrg }
1331debfc3dSmrg
1341debfc3dSmrg /* Report some basic statistics about the string pool. */
1351debfc3dSmrg
1361debfc3dSmrg void
stringpool_statistics(void)1371debfc3dSmrg stringpool_statistics (void)
1381debfc3dSmrg {
1391debfc3dSmrg ht_dump_statistics (ident_hash);
1401debfc3dSmrg }
1411debfc3dSmrg
1421debfc3dSmrg /* Mark an identifier for GC. */
1431debfc3dSmrg
1441debfc3dSmrg static int
mark_ident(struct cpp_reader * pfile ATTRIBUTE_UNUSED,hashnode h,const void * v ATTRIBUTE_UNUSED)1451debfc3dSmrg mark_ident (struct cpp_reader *pfile ATTRIBUTE_UNUSED, hashnode h,
1461debfc3dSmrg const void *v ATTRIBUTE_UNUSED)
1471debfc3dSmrg {
1481debfc3dSmrg gt_ggc_m_9tree_node (HT_IDENT_TO_GCC_IDENT (h));
1491debfc3dSmrg return 1;
1501debfc3dSmrg }
1511debfc3dSmrg
1521debfc3dSmrg /* Return true if an identifier should be removed from the table. */
1531debfc3dSmrg
1541debfc3dSmrg static int
maybe_delete_ident(struct cpp_reader * pfile ATTRIBUTE_UNUSED,hashnode h,const void * v ATTRIBUTE_UNUSED)1551debfc3dSmrg maybe_delete_ident (struct cpp_reader *pfile ATTRIBUTE_UNUSED, hashnode h,
1561debfc3dSmrg const void *v ATTRIBUTE_UNUSED)
1571debfc3dSmrg {
1581debfc3dSmrg return !ggc_marked_p (HT_IDENT_TO_GCC_IDENT (h));
1591debfc3dSmrg }
1601debfc3dSmrg
1611debfc3dSmrg /* Mark the trees hanging off the identifier node for GGC. These are
1621debfc3dSmrg handled specially (not using gengtype) because identifiers are only
1631debfc3dSmrg roots during one part of compilation. */
1641debfc3dSmrg
1651debfc3dSmrg void
ggc_mark_stringpool(void)1661debfc3dSmrg ggc_mark_stringpool (void)
1671debfc3dSmrg {
1681debfc3dSmrg ht_forall (ident_hash, mark_ident, NULL);
1691debfc3dSmrg }
1701debfc3dSmrg
1711debfc3dSmrg /* Purge the identifier hash of identifiers which are no longer
1721debfc3dSmrg referenced. */
1731debfc3dSmrg
1741debfc3dSmrg void
ggc_purge_stringpool(void)1751debfc3dSmrg ggc_purge_stringpool (void)
1761debfc3dSmrg {
1771debfc3dSmrg ht_purge (ident_hash, maybe_delete_ident, NULL);
1781debfc3dSmrg }
1791debfc3dSmrg
1801debfc3dSmrg /* Pointer-walking routine for strings (not very interesting, since
1811debfc3dSmrg strings don't contain pointers). */
1821debfc3dSmrg
1831debfc3dSmrg void
gt_pch_p_S(void * obj ATTRIBUTE_UNUSED,void * x ATTRIBUTE_UNUSED,gt_pointer_operator op ATTRIBUTE_UNUSED,void * cookie ATTRIBUTE_UNUSED)1841debfc3dSmrg gt_pch_p_S (void *obj ATTRIBUTE_UNUSED, void *x ATTRIBUTE_UNUSED,
1851debfc3dSmrg gt_pointer_operator op ATTRIBUTE_UNUSED,
1861debfc3dSmrg void *cookie ATTRIBUTE_UNUSED)
1871debfc3dSmrg {
1881debfc3dSmrg }
1891debfc3dSmrg
1901debfc3dSmrg /* PCH pointer-walking routine for strings. */
1911debfc3dSmrg
1921debfc3dSmrg void
gt_pch_n_S(const void * x)1931debfc3dSmrg gt_pch_n_S (const void *x)
1941debfc3dSmrg {
1951debfc3dSmrg gt_pch_note_object (CONST_CAST (void *, x), CONST_CAST (void *, x),
1961debfc3dSmrg >_pch_p_S);
1971debfc3dSmrg }
1981debfc3dSmrg
1991debfc3dSmrg
2001debfc3dSmrg /* User-callable entry point for marking string X. */
2011debfc3dSmrg
2021debfc3dSmrg void
gt_pch_nx(const char * & x)2031debfc3dSmrg gt_pch_nx (const char *& x)
2041debfc3dSmrg {
2051debfc3dSmrg gt_pch_n_S (x);
2061debfc3dSmrg }
2071debfc3dSmrg
2081debfc3dSmrg void
gt_pch_nx(unsigned char * & x)2091debfc3dSmrg gt_pch_nx (unsigned char *& x)
2101debfc3dSmrg {
2111debfc3dSmrg gt_pch_n_S (x);
2121debfc3dSmrg }
2131debfc3dSmrg
2141debfc3dSmrg void
gt_pch_nx(unsigned char & x ATTRIBUTE_UNUSED)2151debfc3dSmrg gt_pch_nx (unsigned char& x ATTRIBUTE_UNUSED)
2161debfc3dSmrg {
2171debfc3dSmrg }
2181debfc3dSmrg
2191debfc3dSmrg void
gt_pch_nx(unsigned char * x,gt_pointer_operator op,void * cookie)2201debfc3dSmrg gt_pch_nx (unsigned char *x, gt_pointer_operator op, void *cookie)
2211debfc3dSmrg {
2221debfc3dSmrg op (x, cookie);
2231debfc3dSmrg }
2241debfc3dSmrg
2251debfc3dSmrg /* Handle saving and restoring the string pool for PCH. */
2261debfc3dSmrg
2271debfc3dSmrg /* SPD is saved in the PCH file and holds the information needed
2281debfc3dSmrg to restore the string pool. */
2291debfc3dSmrg
2301debfc3dSmrg struct GTY(()) string_pool_data {
2311debfc3dSmrg ht_identifier_ptr *
2321debfc3dSmrg GTY((length ("%h.nslots"),
2331debfc3dSmrg nested_ptr (union tree_node, "%h ? GCC_IDENT_TO_HT_IDENT (%h) : NULL",
2341debfc3dSmrg "%h ? HT_IDENT_TO_GCC_IDENT (%h) : NULL")))
2351debfc3dSmrg entries;
2361debfc3dSmrg unsigned int nslots;
2371debfc3dSmrg unsigned int nelements;
2381debfc3dSmrg };
2391debfc3dSmrg
2401debfc3dSmrg static GTY(()) struct string_pool_data * spd;
2411debfc3dSmrg
2421debfc3dSmrg /* Save the stringpool data in SPD. */
2431debfc3dSmrg
2441debfc3dSmrg void
gt_pch_save_stringpool(void)2451debfc3dSmrg gt_pch_save_stringpool (void)
2461debfc3dSmrg {
2471debfc3dSmrg spd = ggc_alloc<string_pool_data> ();
2481debfc3dSmrg spd->nslots = ident_hash->nslots;
2491debfc3dSmrg spd->nelements = ident_hash->nelements;
2501debfc3dSmrg spd->entries = ggc_vec_alloc<ht_identifier_ptr> (spd->nslots);
2511debfc3dSmrg memcpy (spd->entries, ident_hash->entries,
2521debfc3dSmrg spd->nslots * sizeof (spd->entries[0]));
2531debfc3dSmrg }
2541debfc3dSmrg
2551debfc3dSmrg /* Return the stringpool to its state before gt_pch_save_stringpool
2561debfc3dSmrg was called. */
2571debfc3dSmrg
2581debfc3dSmrg void
gt_pch_fixup_stringpool(void)2591debfc3dSmrg gt_pch_fixup_stringpool (void)
2601debfc3dSmrg {
2611debfc3dSmrg }
2621debfc3dSmrg
2631debfc3dSmrg /* A PCH file has been restored, which loaded SPD; fill the real hash table
2641debfc3dSmrg from SPD. */
2651debfc3dSmrg
2661debfc3dSmrg void
gt_pch_restore_stringpool(void)2671debfc3dSmrg gt_pch_restore_stringpool (void)
2681debfc3dSmrg {
2691debfc3dSmrg ht_load (ident_hash, spd->entries, spd->nslots, spd->nelements, false);
2701debfc3dSmrg spd = NULL;
2711debfc3dSmrg }
2721debfc3dSmrg
2731debfc3dSmrg #include "gt-stringpool.h"
274