stringpool.c: New file.
authorZack Weinberg <zack@wolery.stanford.edu>
Fri, 17 Nov 2000 06:05:31 +0000 (06:05 +0000)
committerZack Weinberg <zack@gcc.gnu.org>
Fri, 17 Nov 2000 06:05:31 +0000 (06:05 +0000)
* stringpool.c: New file.
* ggc-common.c (ggc_mark_string_ptr, ggc_add_string_root): Delete.
(ggc_alloc_string): Now in stringpool.o.
* ggc-page.c, ggc-simple.c: Do not define or allocate empty_string.
* ggc.h: Delete prototype of ggc_add_string_root.  #define
ggc_add_string_root and ggc_mark_string to nothing.  Prototype
init_stringpool and stringpool_statistics.
(ggc_alloc_string): Returns a const char *.
* tree.c (hash_table, do_identifier_warnings): Delete.
(init_obstacks): Don't initialize the identifier hash table.
(get_identifier, maybe_get_identifier, start_identifier_warnings,
set_identifier_size): Now in stringpool.c.
* tree.h (struct tree_string): Constify pointer field.
(approx_sqrt): Prototype.

* Makefile.in (stringpool.o): Add rule, mention in OBJS.

* toplev.c (approx_sqrt): New function.
(compile_file): Call stringpool_statistics if mem_report is on.
(main): Call init_stringpool.

* builtins.c (c_strlen), c-decl.c (finish_decl), c-lex.c
(process_directive), c-typeck.c (constructor_asmspec, struct
initializer_stack, start_init), except.c (create_rethrow_ref),
stmt.c (digit_strings), toplev.c (decode_f_option), tree.c
(built_in_filename), varasm,c (in_named_name,
assemble_static_space, struct constant_descriptor, struct
deferred_string, struct pool_constant, force_const_mem),
i386.c (pic_label_name, global_offset_table_name), rs6000.c
(rs6000_emit_prologue, rs6000_emit_epilogue) : Constify a char *.

* c-common.c (combine_strings): Combine strings in scratch
buffer, then pass to build_string.
* optabs.c (init_libfuncs), profile.c (init_edge_profiler,
output_func_start_profiler), stmt.c (init_stmt), alpha.c
(alpha_need_linkage), arm.c (arm_encode_call_attribute),
i386.c (load_pic_register), ia64.c (ia64_encode_section_info),
rs6000.c (rs6000_encode_section_info): Create string in
scratch buffer, then pass to ggc_alloc_string.

* stmt.c (expand_asm_operands): If we must adjust the
constraint strings, do so by creating a new one, not by
modifying the old one in place.  Constify some char *s.
* config/pa/pa.c (hppa_encode_label): Drop unnecessary second
argument.  Create string in scratch buffer, then pass to
ggc_alloc_string.
* config/pa/pa-protos.h: Update prototype.
* config/pa/elf.h, config/pa/pa.h, config/pa/som.h:
hppa_encode_label takes only one argument.

* c-parse.in (if_prefix): Find the filename and line number at
$-2 and $-1 respectively.
* diagnostic.c (error_recursion): Add missing newline, use
fputs, translate string.

cp:
* lex.c (struct impl_files, internal_filename): Constify a char *.
java:
* jcf-parse.c (get_constant), parse.y (do_merge_string_cste):
Create string in scratch buffer, then pass to build_string.

From-SVN: r37514

37 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/builtins.c
gcc/c-common.c
gcc/c-decl.c
gcc/c-lex.c
gcc/c-parse.in
gcc/c-typeck.c
gcc/config/alpha/alpha.c
gcc/config/arm/arm.c
gcc/config/i386/i386.c
gcc/config/ia64/ia64.c
gcc/config/pa/elf.h
gcc/config/pa/pa-protos.h
gcc/config/pa/pa.c
gcc/config/pa/pa.h
gcc/config/pa/som.h
gcc/config/rs6000/rs6000.c
gcc/cp/ChangeLog
gcc/cp/lex.c
gcc/diagnostic.c
gcc/except.c
gcc/ggc-common.c
gcc/ggc-page.c
gcc/ggc-simple.c
gcc/ggc.h
gcc/java/ChangeLog
gcc/java/jcf-parse.c
gcc/java/parse.y
gcc/optabs.c
gcc/profile.c
gcc/stmt.c
gcc/stringpool.c [new file with mode: 0644]
gcc/toplev.c
gcc/tree.c
gcc/tree.h
gcc/varasm.c

index 79a01946dea6e6d90916b5ae364109c8812aec8a..bbb7eeec1ce33919af70140c9b5433603228b105 100644 (file)
@@ -1,3 +1,62 @@
+2000-11-16  Zack Weinberg  <zack@wolery.stanford.edu>
+
+       * c-parse.in (if_prefix): Find the filename and line number at
+       $-2 and $-1 respectively.
+       * diagnostic.c (error_recursion): Add missing newline, use
+       fputs, translate string.
+
+2000-11-16  Zack Weinberg  <zack@wolery.stanford.edu>
+
+       * stringpool.c: New file.
+       * ggc-common.c (ggc_mark_string_ptr, ggc_add_string_root): Delete.
+       (ggc_alloc_string): Now in stringpool.o.
+       * ggc-page.c, ggc-simple.c: Do not define or allocate empty_string.
+       * ggc.h: Delete prototype of ggc_add_string_root.  #define
+       ggc_add_string_root and ggc_mark_string to nothing.  Prototype
+       init_stringpool and stringpool_statistics.
+       (ggc_alloc_string): Returns a const char *.
+       * tree.c (hash_table, do_identifier_warnings): Delete.
+       (init_obstacks): Don't initialize the identifier hash table.
+       (get_identifier, maybe_get_identifier, start_identifier_warnings,
+       set_identifier_size): Now in stringpool.c.
+       * tree.h (struct tree_string): Constify pointer field.
+       (approx_sqrt): Prototype.
+
+       * Makefile.in (stringpool.o): Add rule, mention in OBJS.
+
+       * toplev.c (approx_sqrt): New function.
+       (compile_file): Call stringpool_statistics if mem_report is on.
+       (main): Call init_stringpool.
+
+       * builtins.c (c_strlen), c-decl.c (finish_decl), c-lex.c
+       (process_directive), c-typeck.c (constructor_asmspec, struct
+       initializer_stack, start_init), except.c (create_rethrow_ref),
+       stmt.c (digit_strings), toplev.c (decode_f_option), tree.c
+       (built_in_filename), varasm,c (in_named_name,
+       assemble_static_space, struct constant_descriptor, struct
+       deferred_string, struct pool_constant, force_const_mem),
+       i386.c (pic_label_name, global_offset_table_name), rs6000.c
+       (rs6000_emit_prologue, rs6000_emit_epilogue) : Constify a char *.
+
+       * c-common.c (combine_strings): Combine strings in scratch
+       buffer, then pass to build_string.
+       * optabs.c (init_libfuncs), profile.c (init_edge_profiler,
+       output_func_start_profiler), stmt.c (init_stmt), alpha.c
+       (alpha_need_linkage), arm.c (arm_encode_call_attribute),
+       i386.c (load_pic_register), ia64.c (ia64_encode_section_info),
+       rs6000.c (rs6000_encode_section_info): Create string in
+       scratch buffer, then pass to ggc_alloc_string.
+
+       * stmt.c (expand_asm_operands): If we must adjust the
+       constraint strings, do so by creating a new one, not by
+       modifying the old one in place.  Constify some char *s.
+       * config/pa/pa.c (hppa_encode_label): Drop unnecessary second
+       argument.  Create string in scratch buffer, then pass to
+       ggc_alloc_string.
+       * config/pa/pa-protos.h: Update prototype.
+       * config/pa/elf.h, config/pa/pa.h, config/pa/som.h:
+       hppa_encode_label takes only one argument.
+
 2000-11-16  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * mcore.c (mcore_expand_prolog): Call xmalloc/xrealloc, not
index ff820d85f53c0dc693f4616dcd88d85b2ce2347e..d07357e31f6e4cffee6bd9df59a4f4509250bb11 100644 (file)
@@ -734,7 +734,7 @@ OBJS = diagnostic.o version.o tree.o print-tree.o stor-layout.o fold-const.o  \
  insn-opinit.o insn-recog.o insn-extract.o insn-output.o insn-emit.o lcm.o    \
  profile.o insn-attrtab.o $(out_object_file) $(EXTRA_OBJS) convert.o         \
  mbchar.o splay-tree.o graph.o sbitmap.o resource.o hash.o predict.o         \
- lists.o ggc-common.o $(GGC) simplify-rtx.o ssa.o bb-reorder.o               \
+ lists.o ggc-common.o $(GGC) stringpool.o simplify-rtx.o ssa.o bb-reorder.o   \
  sibcall.o conflict.o timevar.o ifcvt.o dominance.o dependence.o dce.o
 
 BACKEND = toplev.o libbackend.a
@@ -1268,6 +1268,9 @@ ggc-simple.o: ggc-simple.c $(CONFIG_H) $(RTL_H) $(TREE_H) flags.h \
 ggc-page.o: ggc-page.c $(CONFIG_H) $(RTL_H) $(TREE_H) flags.h toplev.h \
        $(GGC_H) varray.h $(TIMEVAR_H)
 
+stringpool.o: stringpool.c $(CONFIG_H) system.h $(TREE_H) $(OBSTACK_H) \
+       flags.h toplev.h
+
 ggc-none.o: ggc-none.c $(CONFIG_H) $(RTL_H) $(GGC_H)
 
 obstack.o: $(srcdir)/../libiberty/obstack.c $(CONFIG_H)
index 8daf963a6b2178babd5ed2d7dc1c2fb9873dc9c8..ec12cae98ce2667d3d98bbf1ade1b3124ea13550 100644 (file)
@@ -210,7 +210,7 @@ c_strlen (src)
 {
   tree offset_node;
   int offset, max;
-  char *ptr;
+  const char *ptr;
 
   src = string_constant (src, &offset_node);
   if (src == 0)
index 50620f0ec6a457d3d4a66be421a9b7be751a9be1..05b7b8a5df0076e2b84a4d6c295ac9c52df8a0c9 100644 (file)
@@ -377,7 +377,7 @@ combine_strings (strings)
       if (wide_flag)
        length = length * wchar_bytes + wide_length;
 
-      p = ggc_alloc_string (NULL, length);
+      p = alloca (length);
 
       /* Copy the individual strings into the new combined string.
         If the combined string is wide, convert the chars to ints
@@ -416,9 +416,7 @@ combine_strings (strings)
       else
        *q = 0;
 
-      value = make_node (STRING_CST);
-      TREE_STRING_POINTER (value) = p;
-      TREE_STRING_LENGTH (value) = length;
+      value = build_string (length, p);
     }
   else
     {
index d9ceac8988ef3f749fcbd60064ea53ff6214c812..8d66b4ef26053478d7d657dab2c69a5898b3cb4c 100644 (file)
@@ -3634,7 +3634,7 @@ finish_decl (decl, init, asmspec_tree)
 {
   register tree type = TREE_TYPE (decl);
   int was_incomplete = (DECL_SIZE (decl) == 0);
-  char *asmspec = 0;
+  const char *asmspec = 0;
 
   /* If a name was specified, get the string.   */
   if (asmspec_tree)
index 7f1160481bf8427093adf164f6c7e2cf098a4f47..61ff1553cdbe279ebe8e682b1f147f3d33ddfebc 100644 (file)
@@ -443,7 +443,7 @@ process_directive ()
   int saw_line;
   enum { act_none, act_push, act_pop } action;
   int action_number, l;
-  char *new_file;
+  const char *new_file;
 #ifndef NO_IMPLICIT_EXTERN_C
   int entering_c_header = 0;
 #endif
index 288d248e52a5b8becea5c191a2f44bbce8ba5c80..ae474667ff633e9b27a90b867d2436eec8fdc095 100644 (file)
@@ -1765,8 +1765,8 @@ if_prefix:
                { c_expand_start_cond (truthvalue_conversion ($3), 
                                       compstmt_count);
                  $<itype>$ = stmt_count;
-                 if_stmt_file = $<filename>-1;
-                 if_stmt_line = $<lineno>0; }
+                 if_stmt_file = $<filename>-2;
+                 if_stmt_line = $<lineno>-1; }
        ;
 
 /* This is a subroutine of stmt.
index 09f4089b5b361b4db99da6d0ed7e8a05430ee87f..edf73ea00bef1f86b0faf3c7cec3094fb838e22b 100644 (file)
@@ -4944,7 +4944,7 @@ static int require_constant_elements;
 static tree constructor_decl;
 
 /* start_init saves the ASMSPEC arg here for really_start_incremental_init.  */
-static char *constructor_asmspec;
+static const char *constructor_asmspec;
 
 /* Nonzero if this is an initializer for a top-level decl.  */
 static int constructor_top_level;
@@ -4989,7 +4989,7 @@ struct initializer_stack
 {
   struct initializer_stack *next;
   tree decl;
-  char *asmspec;
+  const char *asmspec;
   struct constructor_stack *constructor_stack;
   tree elements;
   struct spelling *spelling;
@@ -5014,7 +5014,7 @@ start_init (decl, asmspec_tree, top_level)
   const char *locus;
   struct initializer_stack *p
     = (struct initializer_stack *) xmalloc (sizeof (struct initializer_stack));
-  char *asmspec = 0;
+  const char *asmspec = 0;
 
   if (asmspec_tree)
     asmspec = TREE_STRING_POINTER (asmspec_tree);
index 06c141f03188c103d80f0b6a9d81fc74cdd4c56d..b4707f22925d31b2cd6be52ba42b3132b42bfd7c 100644 (file)
@@ -6232,12 +6232,12 @@ alpha_need_linkage (name, is_local)
   /* Construct a SYMBOL_REF for us to call.  */
   {
     size_t name_len = strlen (name);
-    char *linksym = ggc_alloc_string (NULL, name_len + 6);
-
+    char *linksym = alloca (name_len + 6);
     linksym[0] = '$';
     memcpy (linksym + 1, name, name_len);
     memcpy (linksym + 1 + name_len, "..lk", 5);
-    al->linkage = gen_rtx_SYMBOL_REF (Pmode, linksym);
+    al->linkage = gen_rtx_SYMBOL_REF (Pmode,
+                                     ggc_alloc_string (linksym, name_len + 5));
   }
 
   splay_tree_insert (alpha_links, (splay_tree_key) name,
index 3bb55227ff13e2e7c40ff6004576bd8853fd7902..3d7121e0f573db87f7f8f52b6a0a61254d572c1d 100644 (file)
@@ -1726,11 +1726,12 @@ arm_encode_call_attribute (decl, flag)
   /* Do not allow weak functions to be treated as short call.  */
   if (DECL_WEAK (decl) && flag == SHORT_CALL_FLAG_CHAR)
     return;
-  
-  newstr = ggc_alloc_string (NULL, len + 2);
 
-  sprintf (newstr, "%c%s", flag, str);
+  newstr = alloca (len + 2);
+  newstr[0] = flag;
+  strcpy (newstr + 1, str);
 
+  newstr = ggc_alloc_string (newstr, len + 1);
   XSTR (XEXP (DECL_RTL (decl), 0), 0) = newstr;
 }
 
index 396df6eb7954386ca85ff2ab57d47e4a401693ea..f5aee19ec04bf8572a666f3fed77dda930326359 100644 (file)
@@ -1675,9 +1675,9 @@ ix86_can_use_return_insn_p ()
   return tsize == 0 && nregs == 0;
 }
 \f
-static char *pic_label_name;
+static const char *pic_label_name;
 static int pic_label_output;
-static char *global_offset_table_name;
+static const char *global_offset_table_name;
 
 /* This function generates code for -fpic that loads %ebx with
    the return address of the caller and then returns.  */
@@ -1733,9 +1733,10 @@ load_pic_register ()
     {
       if (pic_label_name == NULL)
        {
-         pic_label_name = ggc_alloc_string (NULL, 32);
+         char buf[32];
+         ASM_GENERATE_INTERNAL_LABEL (buf, "LPR", 0);
+         pic_label_name = ggc_alloc_string (buf, -1);
          ggc_add_string_root (&pic_label_name, 1);
-         ASM_GENERATE_INTERNAL_LABEL (pic_label_name, "LPR", 0);
        }
       pclab = gen_rtx_MEM (QImode, gen_rtx_SYMBOL_REF (Pmode, pic_label_name));
     }
index ee8121f819843132c31a562d8b92c6357575a358..0f6657a2adc11d577c6f57093d032e9a5cd05a84 100644 (file)
@@ -4801,12 +4801,12 @@ ia64_encode_section_info (decl)
               && symbol_str[0] != SDATA_NAME_FLAG_CHAR)
        {
          size_t len = strlen (symbol_str);
-         char *newstr;
+         char *newstr = alloca (len + 1);
 
-         newstr = ggc_alloc_string (NULL, len + 1);
          *newstr = SDATA_NAME_FLAG_CHAR;
          memcpy (newstr + 1, symbol_str, len + 1);
-
+         
+         newstr = ggc_alloc_string (newstr, len + 1);
          XSTR (XEXP (DECL_RTL (decl), 0), 0) = newstr;
        }
     }
index 882f5ca16e46fe0c15b43191efd635f53ef129b2..1fda8ad57080b1559cc041b78c6f901b1797ba42 100644 (file)
@@ -84,7 +84,7 @@ do {  \
 #define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, RTL) \
   do { fputs ("\t.IMPORT ", FILE);                                     \
        if (!function_label_operand (RTL, VOIDmode))                    \
-        hppa_encode_label (RTL, 1);                                    \
+        hppa_encode_label (RTL);                                       \
        assemble_name (FILE, XSTR ((RTL), 0));                          \
        fputs (",ENTRY\n", FILE);                                       \
      } while (0)
index 6fd697bc15799f97f5b6df10d70a35556dfd15a6..4f15aa72367f1ad2e40d0d40c94a33637993ccb2 100644 (file)
@@ -61,7 +61,7 @@ extern void output_global_address PARAMS ((FILE *, rtx, int));
 extern void print_operand PARAMS ((FILE *, rtx, int));
 extern rtx legitimize_pic_address PARAMS ((rtx, enum machine_mode, rtx));
 extern struct rtx_def *gen_cmp_fp PARAMS ((enum rtx_code, rtx, rtx));
-extern void hppa_encode_label PARAMS ((rtx, int));
+extern void hppa_encode_label PARAMS ((rtx));
 extern int arith11_operand PARAMS ((rtx, enum machine_mode));
 extern int symbolic_expression_p PARAMS ((rtx));
 extern int hppa_address_cost PARAMS ((rtx));
index 0a5c4495457a21ce4800a5fad0c6a9f695ae1460..540f8a7e4c880831f293bde76854e25afab08620 100644 (file)
@@ -5939,29 +5939,22 @@ output_call (insn, call_dest, sibcall)
 /* In HPUX 8.0's shared library scheme, special relocations are needed
    for function labels if they might be passed to a function
    in a shared library (because shared libraries don't live in code
-   space), and special magic is needed to construct their address.
-
-   For reasons too disgusting to describe storage for the new name
-   is allocated as a ggc string, or as a string on the saveable_obstack
-   (released at function exit) or on the permanent_obstack for things
-   that can never change (libcall names for example). */
+   space), and special magic is needed to construct their address.  */
 
 void
-hppa_encode_label (sym, permanent)
+hppa_encode_label (sym)
      rtx sym;
-     int permanent;
 {
   const char *str = XSTR (sym, 0);
   int len = strlen (str);
-  char *newstr;
-
-  newstr = ggc_alloc_string (NULL, len + 1);
+  char *newstr = alloca (len + 1);
 
   if (str[0] == '*')
     *newstr++ = *str++;
   strcpy (newstr + 1, str);
   *newstr = '@';
-  XSTR (sym,0) = newstr;
+
+  XSTR (sym,0) = ggc_alloc_string (newstr, len);
 }
 
 int
index 223674634d4262c42365a30634963efbf20ef97e..536692b54054991eda02419412fd3243a8bf4164 100644 (file)
@@ -1494,7 +1494,7 @@ do                                                        \
          _rtl = TREE_CST_RTL (DECL);                   \
        SYMBOL_REF_FLAG (XEXP (_rtl, 0)) = 1;           \
        if (TREE_CODE (DECL) == FUNCTION_DECL)          \
-         hppa_encode_label (XEXP (DECL_RTL (DECL), 0), 0);\
+         hppa_encode_label (XEXP (DECL_RTL (DECL), 0));\
       }                                                        \
   }                                                    \
 while (0)
index 073f79816de98e86007c0db184a092f5ba19537b..06ee54b107b3288fda38a9ec569496cdc7887e9a 100644 (file)
@@ -352,7 +352,7 @@ DTORS_SECTION_FUNCTION
 #define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, RTL) \
   do { fputs ("\t.IMPORT ", FILE);                                     \
        if (!function_label_operand (RTL, VOIDmode))                    \
-        hppa_encode_label (RTL, 1);                                    \
+        hppa_encode_label (RTL);                                       \
        assemble_name (FILE, XSTR ((RTL), 0));                          \
        fputs (",CODE\n", FILE);                                                \
      } while (0)
index bbefa7e2a883c360eabbaa1565c089d7a42bfcf1..98fb376704f8110af581a7f67562530983dd5096 100644 (file)
@@ -5604,7 +5604,7 @@ rs6000_emit_prologue()
     {
       int i;
       char rname[30];
-      char *alloc_rname;
+      const char *alloc_rname;
       rtvec p;
       p = rtvec_alloc (2 + 64 - info->first_fp_reg_save);
       
@@ -6057,7 +6057,7 @@ rs6000_emit_epilogue(sibcall)
        {
          int i;
          char rname[30];
-         char *alloc_rname;
+         const char *alloc_rname;
 
          sprintf (rname, "%s%d%s", RESTORE_FP_PREFIX, 
                   info->first_fp_reg_save - 32, RESTORE_FP_SUFFIX);
@@ -7578,14 +7578,12 @@ rs6000_encode_section_info (decl)
        {
          size_t len1 = (DEFAULT_ABI == ABI_AIX) ? 1 : 2;
          size_t len2 = strlen (XSTR (sym_ref, 0));
-         char *str;
-
-         str = ggc_alloc_string (NULL, len1 + len2);
+         char *str = alloca (len1 + len2 + 1);
          str[0] = '.';
          str[1] = '.';
          memcpy (str + len1, XSTR (sym_ref, 0), len2 + 1);
 
-         XSTR (sym_ref, 0) = str;
+         XSTR (sym_ref, 0) = ggc_alloc_string (str, len1 + len2);
        }
     }
   else if (rs6000_sdata != SDATA_NONE
@@ -7625,13 +7623,11 @@ rs6000_encode_section_info (decl)
        {
          rtx sym_ref = XEXP (DECL_RTL (decl), 0);
          size_t len = strlen (XSTR (sym_ref, 0));
-         char *str;
+         char *str = alloca (len + 1);
 
-         str = ggc_alloc_string (NULL, len + 1);
          str[0] = '@';
          memcpy (str + 1, XSTR (sym_ref, 0), len + 1);
-
-         XSTR (sym_ref, 0) = str;
+         XSTR (sym_ref, 0) = ggc_alloc_string (str, len);
        }
     }
 }
index 3058f671019f4fd1c40dc513d14891ef5494d69d..a9930eedd647ac1515ff1629eae8b351c4b20c8f 100644 (file)
@@ -1,3 +1,7 @@
+2000-11-16  Zack Weinberg  <zack@wolery.stanford.edu>
+
+       * lex.c (struct impl_files, internal_filename): Constify a char *.
+
 2000-11-16  Mark Mitchell  <mark@codesourcery.com>
 
        * mangle.c (write_special_name_constructor): Don't generate
index 0300deecb522c70dd587e3f82dd3d03622d6e85d..d1511f663eb082e593b60fc436f11350be0d4fc5 100644 (file)
@@ -131,7 +131,7 @@ extern int *token_count;
 
 struct impl_files
 {
-  char *filename;
+  const char *filename;
   struct impl_files *next;
 };
 
@@ -140,7 +140,7 @@ static struct impl_files *impl_file_chain;
 /* The string used to represent the filename of internally generated
    tree nodes.  The variable, which is dynamically allocated, should
    be used; the macro is only used to initialize it.  */
-static char *internal_filename;
+static const char *internal_filename;
 #define INTERNAL_FILENAME ("<internal>")
 \f
 /* Return something to represent absolute declarators containing a *.
index 036b1ce3c90990aacf4183e5efdbe7d68ac025a4..85e3650164b0289269ababd769cecc1c871c019d 100644 (file)
@@ -1637,8 +1637,8 @@ error_recursion ()
   if (diagnostic_lock < 3)
     finish_diagnostic ();
 
-  fprintf (stderr,
-          "Internal compiler error: Error reporting routines re-entered.");
+  fputs (_("Internal compiler error: Error reporting routines re-entered.\n"),
+        stderr);
   finish_abort ();
 }
 
index d3a0a3ca509de5c4051cef32288d1d113693ea3b..e7c5f7d2273d9637695db533d00ec2ee493720cb 100644 (file)
@@ -500,7 +500,7 @@ create_rethrow_ref (region_num)
      int region_num;
 {
   rtx def;
-  char *ptr;
+  const char *ptr;
   char buf[60];
 
   ASM_GENERATE_INTERNAL_LABEL (buf, "LRTH", region_num);
index 2915b731f396d1c3fd74b5d3a41741dfc979ee58..1b083818b151055dac4f1ac7bfb4aa1a032c5599 100644 (file)
@@ -47,7 +47,6 @@ static void ggc_mark_tree_ptr PARAMS ((void *));
 static void ggc_mark_rtx_varray_ptr PARAMS ((void *));
 static void ggc_mark_tree_varray_ptr PARAMS ((void *));
 static void ggc_mark_tree_hash_table_ptr PARAMS ((void *));
-static void ggc_mark_string_ptr PARAMS ((void *));
 static void ggc_mark_trees PARAMS ((void));
 static boolean ggc_mark_tree_hash_table_entry PARAMS ((struct hash_entry *,
                                                       hash_table_key));
@@ -143,16 +142,6 @@ ggc_add_tree_hash_table_root (base, nelt)
                ggc_mark_tree_hash_table_ptr);
 }
 
-/* Register an array of strings as a GC root.  */
-
-void
-ggc_add_string_root (base, nelt)
-     char **base;
-     int nelt;
-{
-  ggc_add_root (base, nelt, sizeof (char *), ggc_mark_string_ptr);
-}
-
 /* Remove the previously registered GC root at BASE.  */
 
 void
@@ -557,43 +546,6 @@ ggc_mark_tree_hash_table_ptr (elt)
   ggc_mark_tree_hash_table (*(struct hash_table **) elt);
 }
 
-/* Type-correct function to pass to ggc_add_root.  It just forwards
-   ELT (which is really a char **) to ggc_mark_string.  */
-
-static void
-ggc_mark_string_ptr (elt)
-     void *elt;
-{
-  ggc_mark_string (*(char **) elt);
-}
-
-/* Allocate a gc-able string.  If CONTENTS is null, then the memory will
-   be uninitialized.  If LENGTH is -1, then CONTENTS is assumed to be a
-   null-terminated string and the memory sized accordingly.  Otherwise,
-   the memory is filled with LENGTH bytes from CONTENTS.  */
-
-char *
-ggc_alloc_string (contents, length)
-     const char *contents;
-     int length;
-{
-  char *string;
-
-  if (length < 0)
-    {
-      if (contents == NULL)
-       return NULL;
-      length = strlen (contents);
-    }
-
-  string = (char *) ggc_alloc (length + 1);
-  if (contents != NULL)
-    memcpy (string, contents, length);
-  string[length] = 0;
-
-  return string;
-}
-
 /* Allocate a block of memory, then clear it.  */
 void *
 ggc_alloc_cleared (size)
index 8744129aaaff6712dbc140b6a839187114978918..2b64f45db53e88a6dc12df2427cf312013bdc67a 100644 (file)
@@ -99,8 +99,6 @@ Boston, MA 02111-1307, USA.  */
 #define HOST_BITS_PER_PTR  HOST_BITS_PER_LONG
 #endif
 
-/* The "" allocated string.  */
-char *empty_string;
 \f
 /* A two-level tree is used to look up the page-entry for a given
    pointer.  Two chunks of the pointer's bits are extracted to index
@@ -839,9 +837,6 @@ init_ggc ()
     munmap (p, G.pagesize);
   }
 #endif
-
-  empty_string = ggc_alloc_string ("", 0);
-  ggc_add_string_root (&empty_string, 1);
 }
 
 /* Increment the `GC context'.  Objects allocated in an outer context
index 7822bb916f3d90875a97bef7e5603cabee9d56ff..b5cab1bcb23b355f91df98199523ae5818354e51 100644 (file)
 #define GGC_ALWAYS_COLLECT
 #endif
 
-/* Constants for general use.  */
-
-char *empty_string;
-
 #ifndef HOST_BITS_PER_PTR
 #define HOST_BITS_PER_PTR  HOST_BITS_PER_LONG
 #endif
@@ -374,9 +370,6 @@ void
 init_ggc ()
 {
   G.allocated_last_gc = GGC_MIN_LAST_ALLOCATED;
-
-  empty_string = ggc_alloc_string ("", 0);
-  ggc_add_string_root (&empty_string, 1);
 }
 
 /* Start a new GGC context.  Memory allocated in previous contexts
index 373026ce464bf18f813d20ba9e008f5f762ee4d0..596c49b49895d8bd9a2b840f5e5dcf2656d73d3f 100644 (file)
--- a/gcc/ggc.h
+++ b/gcc/ggc.h
@@ -40,7 +40,7 @@ union  tree_node;
 struct varasm_status;
 
 /* Constants for general use.  */
-extern char *empty_string;
+extern const char empty_string[];
 
 /* Trees that have been marked, but whose children still need marking.  */
 extern varray_type ggc_pending_trees;
@@ -49,12 +49,14 @@ extern varray_type ggc_pending_trees;
 void ggc_add_root PARAMS ((void *base, int nelt, int size, void (*)(void *)));
 void ggc_add_rtx_root PARAMS ((struct rtx_def **, int nelt));
 void ggc_add_tree_root PARAMS ((union tree_node **, int nelt));
-void ggc_add_string_root PARAMS ((char **, int nelt));
 void ggc_add_rtx_varray_root PARAMS ((struct varray_head_tag **, int nelt));
 void ggc_add_tree_varray_root PARAMS ((struct varray_head_tag **, int nelt));
 void ggc_add_tree_hash_table_root PARAMS ((struct hash_table **, int nelt));
 void ggc_del_root PARAMS ((void *base));
 
+/* Temporary */
+#define ggc_add_string_root(ptr, nelt)  /* nothing */
+
 /* Mark nodes from the gc_add_root callback.  These functions follow
    pointers to mark other objects too.  */
 extern void ggc_mark_rtx_varray PARAMS ((struct varray_head_tag *));
@@ -91,12 +93,8 @@ extern void ggc_mark_rtvec_children PARAMS ((struct rtvec_def *));
       ggc_mark_rtvec_children (v__);            \
   } while (0)
 
-#define ggc_mark_string(EXPR)                  \
-  do {                                         \
-    const char *s__ = (EXPR);                  \
-    if (s__ != NULL)                           \
-      ggc_set_mark (s__);                      \
-  } while (0)
+/* Temporary */
+#define ggc_mark_string(EXPR)  /* nothing */
 
 #define ggc_mark(EXPR)                         \
   do {                                         \
@@ -112,6 +110,7 @@ extern void ggc_mark_if_gcable PARAMS ((const void *));
 
 /* Initialize the garbage collector.   */
 extern void init_ggc PARAMS ((void));
+extern void init_stringpool PARAMS ((void));
 
 /* Start a new GGC context.  Memory allocated in previous contexts
    will not be collected while the new context is active.  */
@@ -138,11 +137,10 @@ void *ggc_alloc_cleared PARAMS ((size_t));
 
 #define ggc_alloc_tree(LENGTH) ((union tree_node *) ggc_alloc (LENGTH))
 
-/* Allocate a gc-able string.  If CONTENTS is null, then the memory will
-   be uninitialized.  If LENGTH is -1, then CONTENTS is assumed to be a
-   null-terminated string and the memory sized accordingly.  Otherwise,
-   the memory is filled with LENGTH bytes from CONTENTS.  */
-char *ggc_alloc_string PARAMS ((const char *contents, int length));
+/* Allocate a gc-able string, and fill it with LENGTH bytes from CONTENTS.
+   If LENGTH is -1, then CONTENTS is assumed to be a
+   null-terminated string and the memory sized accordingly.  */
+const char *ggc_alloc_string PARAMS ((const char *contents, int length));
 
 /* Make a copy of S, in GC-able memory.  */
 #define ggc_strdup(S) ggc_alloc_string((S), -1)
@@ -214,3 +212,4 @@ void ggc_print_common_statistics PARAMS ((FILE *, ggc_statistics *));
 
 /* Print allocation statistics.  */
 extern void ggc_print_statistics PARAMS ((void));
+void stringpool_statistics PARAMS ((void));
index 156bcc15720f5e185a06bfc475aaf00a4bae12c5..5fb49c0a9e73199c7907cdbc00df81595c482e7b 100644 (file)
@@ -1,3 +1,8 @@
+2000-11-16  Zack Weinberg  <zack@wolery.stanford.edu>
+
+       * jcf-parse.c (get_constant), parse.y (do_merge_string_cste):
+       Create string in scratch buffer, then pass to build_string.
+
 2000-11-13  Joseph S. Myers  <jsm28@cam.ac.uk>
 
        * parse.y (issue_warning_error_from_context): Add
index 82c92ee19462a9f619458e76832ade4f2b07ee50..aa56811a630b1e32fd311a1c6616693b4cb19b5b 100644 (file)
@@ -328,29 +328,33 @@ get_constant (jcf, index)
       {
        tree name = get_name_constant (jcf, JPOOL_USHORT1 (jcf, index));
        const char *utf8_ptr = IDENTIFIER_POINTER (name);
-       unsigned char *str_ptr;
        int utf8_len = IDENTIFIER_LENGTH (name);
-       const unsigned char *str = (const unsigned char *)utf8_ptr;
-       int i = utf8_len;
-       int str_len;
+       unsigned char *str_ptr;
+       unsigned char *str;
+       const unsigned char *utf8;
+       int i, str_len;
 
        /* Count the number of Unicode characters in the string,
           while checking for a malformed Utf8 string. */
-       for (str_len = 0; i > 0; str_len++)
+       utf8 = (const unsigned char *) utf8_ptr;
+       i = utf8_len;
+       str_len = 0;
+       while (i > 0)
          {
-           int char_len = UT8_CHAR_LENGTH (*str);
+           int char_len = UT8_CHAR_LENGTH (*utf8);
            if (char_len < 0 || char_len > 3 || char_len > i)
              fatal ("bad string constant");
-           str += char_len;
+           utf8 += char_len;
            i -= char_len;
+           str_len++;
          }
 
-       value = make_node (STRING_CST);
-       TREE_TYPE (value) = build_pointer_type (string_type_node);
-       TREE_STRING_LENGTH (value) = 2 * str_len;
-       TREE_STRING_POINTER (value) = ggc_alloc (2 * str_len);
-       str_ptr = (unsigned char *) TREE_STRING_POINTER (value);
-       str = (const unsigned char *)utf8_ptr;
+       /* Allocate a scratch buffer, convert the string to UCS2, and copy it
+          into the new space.  */
+       str_ptr = (unsigned char *) alloca (2 * str_len);
+       str = str_ptr;
+       utf8 = (const unsigned char *)utf8_ptr;
+
        for (i = 0; i < str_len; i++)
          {
            int char_value;
@@ -358,31 +362,33 @@ get_constant (jcf, index)
            switch (char_len)
              {
              case 1:
-               char_value = *str++;
+               char_value = *utf8++;
                break;
              case 2:
-               char_value = *str++ & 0x1F;
-               char_value = (char_value << 6) | (*str++ & 0x3F);
+               char_value = *utf8++ & 0x1F;
+               char_value = (char_value << 6) | (*utf8++ & 0x3F);
                break;
              case 3:
-               char_value = *str++ & 0x0F;
-               char_value = (char_value << 6) | (*str++ & 0x3F);
-               char_value = (char_value << 6) | (*str++ & 0x3F);
+               char_value = *utf8++ & 0x0F;
+               char_value = (char_value << 6) | (*utf8++ & 0x3F);
+               char_value = (char_value << 6) | (*utf8++ & 0x3F);
                break;
              default:
                goto bad;
              }
            if (BYTES_BIG_ENDIAN)
              {
-               *str_ptr++ = char_value >> 8;
-               *str_ptr++ = char_value & 0xFF;
+               *str++ = char_value >> 8;
+               *str++ = char_value & 0xFF;
              }
            else
              {
-               *str_ptr++ = char_value & 0xFF;
-               *str_ptr++ = char_value >> 8;
+               *str++ = char_value & 0xFF;
+               *str++ = char_value >> 8;
              }
          }
+       value = build_string (str - str_ptr, str_ptr);
+       TREE_TYPE (value) = build_pointer_type (string_type_node);
       }
       break;
     default:
index e422c85082a4a87d56e8f14a906fc765ce1e269d..a35e6dc22ec6b7df77279c404a10bae27fd90778 100644 (file)
@@ -13070,11 +13070,7 @@ do_merge_string_cste (cste, string, string_len, after)
   const char *old = TREE_STRING_POINTER (cste);
   int old_len = TREE_STRING_LENGTH (cste);
   int len = old_len + string_len;
-  char *new;
-  
-  cste = make_node (STRING_CST);
-  TREE_STRING_LENGTH (cste) = len;
-  new = TREE_STRING_POINTER (cste) = ggc_alloc (len+1);
+  char *new = alloca (len+1);
 
   if (after)
     {
@@ -13087,7 +13083,7 @@ do_merge_string_cste (cste, string, string_len, after)
       memcpy (&new [old_len], string, string_len);
     }
   new [len] = '\0';
-  return cste;
+  return build_string (len, new);
 }
 
 /* Tries to merge OP1 (a STRING_CST) and OP2 (if suitable). Return a
index 5f046da9646d3ad6c876a1611f141135a2728620..5ee436d7bf7d4e3c7657c21a8005cbda3fbd2add 100644 (file)
@@ -4466,8 +4466,7 @@ init_libfuncs (optable, first_mode, last_mode, opname, suffix)
     {
       register const char *mname = GET_MODE_NAME(mode);
       register unsigned mname_len = strlen (mname);
-      register char *libfunc_name
-       = ggc_alloc_string (NULL, 2 + opname_len + mname_len + 1 + 1);
+      register char *libfunc_name = alloca (2 + opname_len + mname_len + 1 + 1);
       register char *p;
       register const char *q;
 
@@ -4479,10 +4478,11 @@ init_libfuncs (optable, first_mode, last_mode, opname, suffix)
       for (q = mname; *q; q++)
        *p++ = TOLOWER (*q);
       *p++ = suffix;
-      *p++ = '\0';
+      *p = '\0';
 
       optable->handlers[(int) mode].libfunc
-       = gen_rtx_SYMBOL_REF (Pmode, libfunc_name);
+       = gen_rtx_SYMBOL_REF (Pmode, ggc_alloc_string (libfunc_name,
+                                                      p - libfunc_name));
     }
 }
 
index b52b35257be00686e8ecf7be4142d21710eec25f..d60b2b2227c597257f9f10d7fa47b918e8881ff0 100644 (file)
@@ -1025,9 +1025,9 @@ static void
 init_edge_profiler ()
 {
   /* Generate and save a copy of this so it can be shared.  */
-  char *name = ggc_alloc_string (NULL, 20);
-  ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2);
-  profiler_label = gen_rtx_SYMBOL_REF (Pmode, name);
+  char buf[20];
+  ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", 2);
+  profiler_label = gen_rtx_SYMBOL_REF (Pmode, ggc_alloc_string (buf, -1));
   ggc_add_rtx_root (&profiler_label, 1);
 }
 
@@ -1066,6 +1066,7 @@ output_func_start_profiler ()
 {
   tree fnname, fndecl;
   char *name;
+  char buf[20];
   const char *cfnname;
   rtx table_address;
   enum machine_mode mode = mode_for_size (LONG_TYPE_SIZE, MODE_INT, 0);
@@ -1121,9 +1122,10 @@ output_func_start_profiler ()
   expand_function_start (fndecl, 0);
 
   /* Actually generate the code to call __bb_init_func. */
-  name = ggc_alloc_string (NULL, 20);
-  ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 0);
-  table_address = force_reg (Pmode, gen_rtx_SYMBOL_REF (Pmode, name));
+  ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", 0);
+  table_address = force_reg (Pmode,
+                            gen_rtx_SYMBOL_REF (Pmode,
+                                                ggc_alloc_string (buf, -1)));
   emit_library_call (gen_rtx_SYMBOL_REF 
                     (Pmode, ggc_alloc_string ("__bb_init_func", 14)), 0,
                     mode, 1, table_address, Pmode);
index 82a390d1da122ea8c5a471b8f60c9613f096a782..4ec3fd52c89920957c88ea905bd00cceb1e37e04 100644 (file)
@@ -394,7 +394,7 @@ struct stmt_status
 static int using_eh_for_cleanups_p = 0;
 
 /* Character strings, each containing a single decimal digit.  */
-static char *digit_strings[10];
+static const char *digit_strings[10];
 
 static int n_occurrences               PARAMS ((int, const char *));
 static void expand_goto_internal       PARAMS ((tree, rtx, rtx));
@@ -598,13 +598,15 @@ void
 init_stmt ()
 {
   int i;
+  char buf[2];
 
   gcc_obstack_init (&stmt_obstack);
 
+  buf[1] = 0;
   for (i = 0; i < 10; i++)
     {
-      digit_strings[i] = ggc_alloc_string (NULL, 1);
-      digit_strings[i][0] = '0' + i;
+      buf[0] = '0' + i;
+      digit_strings[i] = ggc_alloc_string (buf, 1);
     }
   ggc_add_string_root (digit_strings, 10);
 }
@@ -1408,7 +1410,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
     {
       tree val = TREE_VALUE (tail);
       tree type = TREE_TYPE (val);
-      char *constraint;
+      const char *constraint;
       char *p;
       int c_len;
       int j;
@@ -1425,8 +1427,8 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
         the worst that happens if we get it wrong is we issue an error
         message.  */
 
-      c_len = strlen (TREE_STRING_POINTER (TREE_PURPOSE (tail)));
       constraint = TREE_STRING_POINTER (TREE_PURPOSE (tail));
+      c_len = strlen (constraint);
 
       /* Allow the `=' or `+' to not be at the beginning of the string,
         since it wasn't explicitly documented that way, and there is a
@@ -1443,19 +1445,25 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
          error ("output operand constraint lacks `='");
          return;
        }
+      j = p - constraint;
+      is_inout = *p == '+';
 
-      if (p != constraint)
+      if (j || is_inout)
        {
-         j = *p;
-         bcopy (constraint, constraint+1, p-constraint);
-         *constraint = j;
-
-         warning ("output constraint `%c' for operand %d is not at the beginning", j, i);
+         /* Have to throw away this constraint string and get a new one.  */
+         char *buf = alloca (c_len + 1);
+         buf[0] = '=';
+         if (j)
+           memcpy (buf + 1, constraint, j);
+         memcpy (buf + 1 + j, p + 1, c_len - j);  /* not -j-1 - copy null */
+         constraint = ggc_alloc_string (buf, c_len);
+
+         if (j)
+           warning (
+               "output constraint `%c' for operand %d is not at the beginning",
+               *p, i);
        }
 
-      is_inout = constraint[0] == '+';
-      /* Replace '+' with '='.  */
-      constraint[0] = '=';
       /* Make sure we can specify the matching operand.  */
       if (is_inout && i > 9)
        {
@@ -1611,7 +1619,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
     {
       int j;
       int allows_reg = 0, allows_mem = 0;
-      char *constraint, *orig_constraint;
+      const char *constraint, *orig_constraint;
       int c_len;
       rtx op;
 
@@ -1629,8 +1637,8 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
          return;
        }
 
-      c_len = strlen (TREE_STRING_POINTER (TREE_PURPOSE (tail)));
       constraint = TREE_STRING_POINTER (TREE_PURPOSE (tail));
+      c_len = strlen (constraint);
       orig_constraint = constraint;
 
       /* Make sure constraint has neither `=', `+', nor '&'.  */
@@ -1691,8 +1699,8 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
                for (j = constraint[j] - '0'; j > 0; --j)
                  o = TREE_CHAIN (o);
 
-               c_len = strlen (TREE_STRING_POINTER (TREE_PURPOSE (o)));
                constraint = TREE_STRING_POINTER (TREE_PURPOSE (o));
+               c_len = strlen (constraint);
                j = 0;
                break;
              }
diff --git a/gcc/stringpool.c b/gcc/stringpool.c
new file mode 100644 (file)
index 0000000..32381e0
--- /dev/null
@@ -0,0 +1,405 @@
+/* String pool for GCC.
+   Copyright (C) 2000 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU CC is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+/* String pool allocator.  All strings allocated by ggc_alloc_string are
+   uniquified and stored in an obstack which is never shrunk.  You can
+   associate a tree with a string if you wish; this is used to implement
+   get_identifier.
+
+   We have our own private hash table implementation which is similar
+   to the one in cpphash.c (actually, it's a further refinement of
+   that code).  libiberty's hashtab.c is not used because it requires
+   100% average space overhead per string, which is unacceptable.
+   Also, this algorithm is faster.  */
+
+#include "config.h"
+#include "system.h"
+#include "ggc.h"
+#include "tree.h"
+#include "obstack.h"
+#include "flags.h"
+#include "toplev.h"
+
+/* The "" allocated string.  */
+const char empty_string[] = "";
+
+static struct obstack string_stack;
+
+/* This is the hash entry associated with each string.  It lives in
+   the hash table; only the string lives in the obstack.  Note that
+   the string is not necessarily NUL terminated.  */
+
+struct str_header
+{
+  const char *ptr;
+  tree data;   /* for get_identifier */
+  unsigned int len;
+};
+
+/* This is the hash table structure.  There's only one.  */
+struct str_hash
+{
+  struct str_header *entries;
+  size_t nslots;       /* total slots in the entries array */
+  size_t nelements;    /* number of live elements */
+
+  /* table usage statistics */
+  unsigned int searches;
+  unsigned int collisions;
+};
+#define INITIAL_HASHSIZE (16*1024)
+
+static struct str_hash string_hash = { 0, INITIAL_HASHSIZE, 0, 0, 0 };
+
+enum insert_option { INSERT, NO_INSERT };
+
+static struct str_header *alloc_string PARAMS ((const char *, size_t,
+                                               enum insert_option));
+static inline unsigned int calc_hash PARAMS ((const unsigned char *, size_t));
+static void mark_string_hash PARAMS ((void *));
+static struct str_header *expand_string_table PARAMS ((struct str_header *));
+
+/* Convenience macro for iterating over the hash table.  E is set to
+   each live entry in turn.  */
+#define FORALL_STRINGS(E) \
+for (E = string_hash.entries; E < string_hash.entries+string_hash.nslots; E++) \
+  if (E->ptr != NULL)
+    /* block here */
+
+/* Likewise, but tests ->data instead of ->ptr (for cases where we only
+   care about entries with ->data set)  */
+#define FORALL_IDS(E) \
+for (E = string_hash.entries; E < string_hash.entries+string_hash.nslots; E++) \
+  if (E->data != NULL)
+
+/* 0 while creating built-in identifiers.  */
+static int do_identifier_warnings;
+
+/* Initialize the string pool.  */
+void
+init_stringpool ()
+{
+  gcc_obstack_init (&string_stack);
+  ggc_add_root (&string_hash, 1, sizeof string_hash, mark_string_hash);
+
+  /* Strings need no alignment.  */
+  obstack_alignment_mask (&string_stack) = 0;
+
+  string_hash.entries = (struct str_header *)
+    xcalloc (string_hash.nslots, sizeof (struct str_header));
+}
+
+/* Enable warnings on similar identifiers (if requested).
+   Done after the built-in identifiers are created.  */
+void
+start_identifier_warnings ()
+{
+  do_identifier_warnings = 1;
+}
+
+/* Record the size of an identifier node for the language in use.
+   SIZE is the total size in bytes.
+   This is called by the language-specific files.  This must be
+   called before allocating any identifiers.  */
+void
+set_identifier_size (size)
+     int size;
+{
+  tree_code_length[(int) IDENTIFIER_NODE]
+    = (size - sizeof (struct tree_common)) / sizeof (tree);
+}
+
+/* Calculate the hash of the string STR, which is of length LEN.  */
+static inline unsigned int
+calc_hash (str, len)
+     const unsigned char *str;
+     size_t len;
+{
+  size_t n = len;
+  unsigned int r = 0;
+#define HASHSTEP(r, c) ((r) * 67 + (c - 113));
+
+  while (n--)
+    r = HASHSTEP (r, *str++);
+
+  return r + len;
+#undef HASHSTEP
+}
+
+/* Internal primitive: returns the header structure for the string of
+   length LENGTH, containing CONTENTS.  If that string already exists
+   in the table, returns the existing entry.  If the string hasn't
+   been seen before and the last argument is INSERT, inserts and returns
+   a new entry. Otherwise returns NULL.  */
+static struct str_header *
+alloc_string (contents, length, insert)
+     const char *contents;
+     size_t length;
+     enum insert_option insert;
+{
+  unsigned int hash = calc_hash ((const unsigned char *)contents, length);
+  unsigned int hash2;
+  unsigned int index;
+  size_t sizemask;
+  struct str_header *entry;
+  struct str_header *entries = string_hash.entries;
+
+  sizemask = string_hash.nslots - 1;
+  index = hash & sizemask;
+
+  /* hash2 must be odd, so we're guaranteed to visit every possible
+     location in the table during rehashing.  */
+  hash2 = ((hash * 17) & sizemask) | 1;
+  string_hash.searches++;
+
+  for (;;)
+    {
+      entry = entries + index;
+
+      if (entry->ptr == NULL)
+       break;
+
+      if (entry->len == length
+         && !memcmp (entry->ptr, contents, length))
+       return entry;
+
+      index = (index + hash2) & sizemask;
+      string_hash.collisions++;
+    }
+
+  if (insert == NO_INSERT)
+    return NULL;
+
+  obstack_grow0 (&string_stack, contents, length);
+  entry->ptr = (const char *) obstack_finish (&string_stack);
+  entry->len = length;
+  entry->data = NULL;
+
+  if (++string_hash.nelements * 4 < string_hash.nslots * 3)
+    return entry;
+
+  /* Must expand the string table.  */
+  return expand_string_table (entry);
+}
+
+/* Subroutine of alloc_string which doubles the size of the hash table
+   and rehashes all the strings into the new table.  Returns the entry
+   in the new table corresponding to ENTRY.  */
+static struct str_header *
+expand_string_table (entry)
+     struct str_header *entry;
+{
+  struct str_header *nentries;
+  struct str_header *e, *nentry = NULL;
+  size_t size, sizemask;
+
+  size = string_hash.nslots * 2;
+  nentries = (struct str_header *) xcalloc (size, sizeof (struct str_header));
+  sizemask = size - 1;
+
+  FORALL_STRINGS (e)
+    {
+      unsigned int index, hash, hash2;
+
+      hash = calc_hash ((const unsigned char *) e->ptr, e->len);
+      hash2 = ((hash * 17) & sizemask) | 1;
+      index = hash & sizemask;
+
+      for (;;)
+       {
+         if (nentries[index].ptr == NULL)
+           {
+             nentries[index].ptr = e->ptr;
+             nentries[index].len = e->len;
+             nentries[index].data = e->data;
+             if (e == entry)
+               nentry = nentries + index;
+             break;
+           }
+
+         index = (index + hash2) & sizemask;
+       }
+    }
+
+  free (string_hash.entries);
+  string_hash.entries = nentries;
+  string_hash.nslots = size;
+  return nentry;
+}
+
+/* Allocate and return a string constant of length LENGTH, containing
+   CONTENTS.  If LENGTH is -1, CONTENTS is assumed to be a
+   nul-terminated string, and the length is calculated using strlen.
+   If the same string constant has been allocated before, that copy is
+   returned this time too.  */
+
+const char *
+ggc_alloc_string (contents, length)
+     const char *contents;
+     int length;
+{
+  struct str_header *str;
+
+  if (length == -1)
+    length = strlen (contents);
+
+  if (length == 0)
+    return empty_string;
+
+  str = alloc_string (contents, length, INSERT);
+  return str->ptr;
+}
+
+/* Return an IDENTIFIER_NODE whose name is TEXT (a null-terminated string).
+   If an identifier with that name has previously been referred to,
+   the same node is returned this time.  */
+tree
+get_identifier (text)
+     const char *text;
+{
+  tree idp;
+  struct str_header *str;
+  size_t length = strlen (text);
+
+  str = alloc_string (text, length, INSERT);
+  idp = str->data;
+  if (idp == NULL)
+    {
+      if (TREE_CODE_LENGTH (IDENTIFIER_NODE) < 0)
+       abort ();       /* set_identifier_size hasn't been called.  */
+
+      /* If this identifier is longer than the clash-warning length,
+        do a brute force search of the entire table for clashes.  */
+      if (warn_id_clash && do_identifier_warnings && length >= (size_t) id_clash_len)
+       {
+         struct str_header *e;
+         FORALL_IDS (e)
+           {
+             if (e->len >= (size_t)id_clash_len
+                 && !strncmp (e->ptr, text, id_clash_len))
+               {
+                 warning ("\"%s\" and \"%s\" identical in first %d characters",
+                          text, e->ptr, id_clash_len);
+                 break;
+               }
+           }
+       }
+
+      idp = make_node (IDENTIFIER_NODE);
+      IDENTIFIER_LENGTH (idp) = length;
+      IDENTIFIER_POINTER (idp) = str->ptr;
+#ifdef GATHER_STATISTICS
+      id_string_size += length;
+#endif
+      str->data = idp;
+    }
+  return idp;
+}
+
+/* If an identifier with the name TEXT (a null-terminated string) has
+   previously been referred to, return that node; otherwise return
+   NULL_TREE.  */
+
+tree
+maybe_get_identifier (text)
+     const char *text;
+{
+  struct str_header *str;
+  size_t length = strlen (text);
+
+  str = alloc_string (text, length, NO_INSERT);
+  if (str)
+    return str->data;  /* N.B. str->data might be null here, if the
+                         string has been used but not as an identifier.  */
+  return NULL_TREE;
+}
+
+/* Report some basic statistics about the string pool.  */
+
+void
+stringpool_statistics ()
+{
+  size_t nelts, overhead, headers;
+  size_t total_bytes, longest, sum_of_squares;
+  double exp_len, exp_len2, exp2_len;
+  struct str_header *e;
+#define SCALE(x) ((unsigned long) ((x) < 1024*10 \
+                 ? (x) \
+                 : ((x) < 1024*1024*10 \
+                    ? (x) / 1024 \
+                    : (x) / (1024*1024))))
+#define LABEL(x) ((x) < 1024*10 ? ' ' : ((x) < 1024*1024*10 ? 'k' : 'M'))
+
+  total_bytes = longest = sum_of_squares = 0;
+  FORALL_STRINGS (e)
+    {
+      size_t n = e->len;
+
+      total_bytes += n;
+      sum_of_squares += n*n;
+      if (n > longest)
+       longest = n;
+    }
+      
+  nelts = string_hash.nelements;
+  overhead = obstack_memory_used (&string_stack) - total_bytes;
+  headers = string_hash.nslots * sizeof (struct str_header);
+
+  fprintf (stderr,
+"\nString pool\n\
+entries\t\t%lu\n\
+slots\t\t%lu\n\
+bytes\t\t%lu%c (%lu%c overhead)\n\
+table size\t%lu%c\n",
+          (unsigned long) nelts, (unsigned long) string_hash.nslots,
+          SCALE (total_bytes), LABEL (total_bytes),
+          SCALE (overhead), LABEL (overhead),
+          SCALE (headers), LABEL (headers));
+
+  exp_len = (double)total_bytes / (double)nelts;
+  exp2_len = exp_len * exp_len;
+  exp_len2 = (double)sum_of_squares / (double)nelts;
+
+  fprintf (stderr,
+"coll/search\t%.4f\n\
+ins/search\t%.4f\n\
+avg. entry\t%.2f bytes (+/- %.2f)\n\
+longest entry\t%lu\n",
+          (double) string_hash.collisions / (double) string_hash.searches,
+          (double) nelts / (double) string_hash.searches,
+          exp_len, approx_sqrt (exp_len2 - exp2_len),
+          (unsigned long) longest);
+#undef SCALE
+#undef LABEL
+}
+
+/* Mark the string hash for GC.  */
+
+static void
+mark_string_hash (arg)
+     void *arg ATTRIBUTE_UNUSED;
+{
+  struct str_header *h;
+
+  FORALL_IDS (h)
+    {
+      ggc_mark_tree (h->data);
+    }
+}
index d25085a715c2ddd33ed91e130597914356ff4c49..592d5fc36045eb1b117ddc11cad6ceb5fbb6c14b 100644 (file)
@@ -1577,6 +1577,29 @@ floor_log2_wide (x)
   return log;
 }
 
+/* Return the approximate positive square root of a number N.  This is for
+   statistical reports, not code generation.  */
+double
+approx_sqrt (x)
+     double x;
+{
+  double s, d;
+
+  if (x < 0)
+    abort ();   
+  if (x == 0)
+    return 0;
+
+  s = x;
+  do
+    {
+      d = (s * s - x) / (2 * s);
+      s -= d;                   
+    }        
+  while (d > .0001);
+  return s;
+}
+
 static int float_handler_set;
 int float_handled;
 jmp_buf float_handler;
@@ -2516,7 +2539,10 @@ compile_file (name)
     }
 
   if (mem_report)
-    ggc_print_statistics ();
+    {
+      ggc_print_statistics ();
+      stringpool_statistics ();
+    }
 
   /* Free up memory for the benefit of leak detectors.  */
   free_reg_info ();
@@ -4085,7 +4111,7 @@ decode_f_option (arg)
   else if ((option_value
            = skip_leading_substring (arg, "stack-limit-symbol=")))
     {
-      char *nm;
+      const char *nm;
       nm = ggc_strdup (option_value);
       stack_limit_rtx = gen_rtx_SYMBOL_REF (Pmode, nm);
     }
@@ -4557,6 +4583,7 @@ main (argc, argv)
 
   /* Initialize the garbage-collector.  */
   init_ggc ();
+  init_stringpool ();
   ggc_add_root (&input_file_stack, 1, sizeof input_file_stack,
                mark_file_stack);
   ggc_add_rtx_root (&stack_limit_rtx, 1);
index 7e820f559cee3a1bba209d5731c8c992593c1b08..28f791b0eba5d110c33ab3e26a074a966259c8ce 100644 (file)
@@ -131,14 +131,6 @@ static const char * const tree_node_kind_names[] = {
   "lang_type kinds"
 };
 
-/* Hash table for uniquizing IDENTIFIER_NODEs by name.  */
-
-#define MAX_HASH_TABLE 1009
-static tree hash_table[MAX_HASH_TABLE];        /* id hash buckets */
-
-/* 0 while creating built-in identifiers.  */
-static int do_identifier_warnings;
-
 /* Unique id for next decl created.  */
 static int next_decl_uid;
 /* Unique id for next type created.  */
@@ -191,7 +183,7 @@ void (*lang_unsave_expr_now) PARAMS ((tree));
    built-in tree nodes.  The variable, which is dynamically allocated,
    should be used; the macro is only used to initialize it.  */
 
-static char *built_in_filename;
+static const char *built_in_filename;
 #define BUILT_IN_FILENAME ("<built-in>")
 \f
 tree global_trees[TI_MAX];
@@ -204,10 +196,6 @@ init_obstacks ()
 {
   gcc_obstack_init (&permanent_obstack);
 
-  /* Init the hash table of identifiers.  */
-  memset ((char *) hash_table, 0, sizeof hash_table);
-  ggc_add_tree_root (hash_table, sizeof hash_table / sizeof (tree));
-
   /* Initialize the hash table of types.  */
   type_hash_table = htab_create (TYPE_HASH_INITIAL_SIZE, type_hash_hash,
                                 type_hash_eq, 0);
@@ -555,133 +543,7 @@ copy_list (list)
     }
   return head;
 }
-\f
-#define HASHBITS 30
-
-/* Return an IDENTIFIER_NODE whose name is TEXT (a null-terminated string).
-   If an identifier with that name has previously been referred to,
-   the same node is returned this time.  */
-
-tree
-get_identifier (text)
-     register const char *text;
-{
-  register int hi;
-  register int i;
-  register tree idp;
-  register int len, hash_len;
-
-  /* Compute length of text in len.  */
-  len = strlen (text);
-
-  /* Decide how much of that length to hash on */
-  hash_len = len;
-  if (warn_id_clash && len > id_clash_len)
-    hash_len = id_clash_len;
-
-  /* Compute hash code */
-  hi = hash_len * 613 + (unsigned) text[0];
-  for (i = 1; i < hash_len; i += 2)
-    hi = ((hi * 613) + (unsigned) (text[i]));
-
-  hi &= (1 << HASHBITS) - 1;
-  hi %= MAX_HASH_TABLE;
-
-  /* Search table for identifier.  */
-  for (idp = hash_table[hi]; idp; idp = TREE_CHAIN (idp))
-    if (IDENTIFIER_LENGTH (idp) == len
-       && IDENTIFIER_POINTER (idp)[0] == text[0]
-       && !memcmp (IDENTIFIER_POINTER (idp), text, len))
-      /* Return if found.  */
-      return idp;
-
-  /* Not found; optionally warn about a similar identifier.  */
-  if (warn_id_clash && do_identifier_warnings && len >= id_clash_len)
-    for (idp = hash_table[hi]; idp; idp = TREE_CHAIN (idp))
-      if (!strncmp (IDENTIFIER_POINTER (idp), text, id_clash_len))
-       {
-         warning ("`%s' and `%s' identical in first %d characters",
-                  IDENTIFIER_POINTER (idp), text, id_clash_len);
-         break;
-       }
-
-  if (TREE_CODE_LENGTH (IDENTIFIER_NODE) < 0)
-    abort ();                  /* set_identifier_size hasn't been called.  */
-
-  /* Not found, create one, add to chain */
-  idp = make_node (IDENTIFIER_NODE);
-  IDENTIFIER_LENGTH (idp) = len;
-#ifdef GATHER_STATISTICS
-  id_string_size += len;
-#endif
-
-  IDENTIFIER_POINTER (idp) = ggc_alloc_string (text, len);
-
-  TREE_CHAIN (idp) = hash_table[hi];
-  hash_table[hi] = idp;
-  return idp;                  /* <-- return if created */
-}
 
-/* If an identifier with the name TEXT (a null-terminated string) has
-   previously been referred to, return that node; otherwise return
-   NULL_TREE.  */
-
-tree
-maybe_get_identifier (text)
-     register const char *text;
-{
-  register int hi;
-  register int i;
-  register tree idp;
-  register int len, hash_len;
-
-  /* Compute length of text in len.  */
-  len = strlen (text);
-
-  /* Decide how much of that length to hash on */
-  hash_len = len;
-  if (warn_id_clash && len > id_clash_len)
-    hash_len = id_clash_len;
-
-  /* Compute hash code */
-  hi = hash_len * 613 + (unsigned) text[0];
-  for (i = 1; i < hash_len; i += 2)
-    hi = ((hi * 613) + (unsigned) (text[i]));
-
-  hi &= (1 << HASHBITS) - 1;
-  hi %= MAX_HASH_TABLE;
-
-  /* Search table for identifier.  */
-  for (idp = hash_table[hi]; idp; idp = TREE_CHAIN (idp))
-    if (IDENTIFIER_LENGTH (idp) == len
-       && IDENTIFIER_POINTER (idp)[0] == text[0]
-       && !memcmp (IDENTIFIER_POINTER (idp), text, len))
-      return idp;              /* <-- return if found */
-
-  return NULL_TREE;
-}
-
-/* Enable warnings on similar identifiers (if requested).
-   Done after the built-in identifiers are created.  */
-
-void
-start_identifier_warnings ()
-{
-  do_identifier_warnings = 1;
-}
-
-/* Record the size of an identifier node for the language in use.
-   SIZE is the total size in bytes.
-   This is called by the language-specific files.  This must be
-   called before allocating any identifiers.  */
-
-void
-set_identifier_size (size)
-     int size;
-{
-  tree_code_length[(int) IDENTIFIER_NODE]
-    = (size - sizeof (struct tree_common)) / sizeof (tree);
-}
 \f
 /* Return a newly constructed INTEGER_CST node whose constant value
    is specified by the two ints LOW and HI.
index a264df4fbdc0f012cb879b71a930f62f9fe6aff0..8f0737649aa559bdd7901309b10cca9f0fd55419 100644 (file)
@@ -713,7 +713,7 @@ struct tree_string
   struct rtx_def *rtl; /* acts as link to register transfer language
                                   (rtl) info */
   int length;
-  char *pointer;
+  const char *pointer;
 };
 
 /* In a COMPLEX_CST node.  */
@@ -1852,6 +1852,10 @@ extern tree integer_types[itk_none];
 extern int exact_log2_wide             PARAMS ((unsigned HOST_WIDE_INT));
 extern int floor_log2_wide             PARAMS ((unsigned HOST_WIDE_INT));
 
+/* Approximate positive square root of a host double.  This is for
+   statistical reports, not code generation.  */
+extern double approx_sqrt              PARAMS ((double));
+
 extern char *permalloc                 PARAMS ((int));
 extern char *expralloc                 PARAMS ((int));
 
index 0fc4ea8aa4a370dcf6721f55725b68ea0a73a8a4..b7d33b2f2b7ba2e65ffaf2a37094d1b1fa30a72c 100644 (file)
@@ -213,7 +213,7 @@ static enum in_section { no_section, in_text, in_data, in_named
 #endif
      
 /* Text of section name when in_section == in_named.  */
-static char *in_named_name;
+static const char *in_named_name;
 
 /* Define functions like text_section for any extra sections.  */
 #ifdef EXTRA_SECTION_FUNCTIONS
@@ -1798,7 +1798,7 @@ assemble_static_space (size)
      int size;
 {
   char name[12];
-  char *namestring;
+  const char *namestring;
   rtx x;
 
 #if 0
@@ -2330,7 +2330,7 @@ struct rtx_const
 struct constant_descriptor
 {
   struct constant_descriptor *next;
-  char *label;
+  const char *label;
   rtx rtl;
   /* Make sure the data is reasonably aligned.  */
   union 
@@ -2352,7 +2352,7 @@ static struct constant_descriptor *const_hash_table[MAX_HASH_TABLE];
 
 struct deferred_string
 {
-  char *label;
+  const char *label;
   tree exp;
   int labelno;
 };
@@ -3335,7 +3335,7 @@ struct pool_constant
 {
   struct constant_descriptor *desc;
   struct pool_constant *next, *next_sym;
-  char *label;
+  const char *label;
   rtx constant;
   enum machine_mode mode;
   int labelno;
@@ -3613,7 +3613,7 @@ force_const_mem (mode, x)
   register int hash;
   register struct constant_descriptor *desc;
   char label[256];
-  char *found = 0;
+  const char *found = 0;
   rtx def;
 
   /* If we want this CONST_DOUBLE in the same mode as it is in memory