xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/stringpool.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
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 		      &gt_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