summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog59
-rw-r--r--gcc/Makefile.in5
-rw-r--r--gcc/builtins.c2
-rw-r--r--gcc/c-common.c6
-rw-r--r--gcc/c-decl.c2
-rw-r--r--gcc/c-lex.c2
-rw-r--r--gcc/c-parse.in4
-rw-r--r--gcc/c-typeck.c6
-rw-r--r--gcc/config/alpha/alpha.c6
-rw-r--r--gcc/config/arm/arm.c7
-rw-r--r--gcc/config/i386/i386.c9
-rw-r--r--gcc/config/ia64/ia64.c6
-rw-r--r--gcc/config/pa/elf.h2
-rw-r--r--gcc/config/pa/pa-protos.h2
-rw-r--r--gcc/config/pa/pa.c17
-rw-r--r--gcc/config/pa/pa.h2
-rw-r--r--gcc/config/pa/som.h2
-rw-r--r--gcc/config/rs6000/rs6000.c16
-rw-r--r--gcc/cp/ChangeLog4
-rw-r--r--gcc/cp/lex.c4
-rw-r--r--gcc/diagnostic.c4
-rw-r--r--gcc/except.c2
-rw-r--r--gcc/ggc-common.c48
-rw-r--r--gcc/ggc-page.c5
-rw-r--r--gcc/ggc-simple.c7
-rw-r--r--gcc/ggc.h25
-rw-r--r--gcc/java/ChangeLog5
-rw-r--r--gcc/java/jcf-parse.c52
-rw-r--r--gcc/java/parse.y8
-rw-r--r--gcc/optabs.c8
-rw-r--r--gcc/profile.c14
-rw-r--r--gcc/stmt.c42
-rw-r--r--gcc/stringpool.c405
-rw-r--r--gcc/toplev.c31
-rw-r--r--gcc/tree.c140
-rw-r--r--gcc/tree.h6
-rw-r--r--gcc/varasm.c12
37 files changed, 643 insertions, 334 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 79a01946dea..bbb7eeec1ce 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index ff820d85f53..d07357e31f6 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -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)
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 8daf963a6b2..ec12cae98ce 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -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)
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 50620f0ec6a..05b7b8a5df0 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -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
{
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index d9ceac8988e..8d66b4ef260 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -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)
diff --git a/gcc/c-lex.c b/gcc/c-lex.c
index 7f1160481bf..61ff1553cdb 100644
--- a/gcc/c-lex.c
+++ b/gcc/c-lex.c
@@ -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
diff --git a/gcc/c-parse.in b/gcc/c-parse.in
index 288d248e52a..ae474667ff6 100644
--- a/gcc/c-parse.in
+++ b/gcc/c-parse.in
@@ -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.
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index 09f4089b5b3..edf73ea00be 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -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);
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 06c141f0318..b4707f22925 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -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,
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 3bb55227ff1..3d7121e0f57 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -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;
}
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 396df6eb795..f5aee19ec04 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -1675,9 +1675,9 @@ ix86_can_use_return_insn_p ()
return tsize == 0 && nregs == 0;
}
-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));
}
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index ee8121f8198..0f6657a2adc 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -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;
}
}
diff --git a/gcc/config/pa/elf.h b/gcc/config/pa/elf.h
index 882f5ca16e4..1fda8ad5708 100644
--- a/gcc/config/pa/elf.h
+++ b/gcc/config/pa/elf.h
@@ -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)
diff --git a/gcc/config/pa/pa-protos.h b/gcc/config/pa/pa-protos.h
index 6fd697bc157..4f15aa72367 100644
--- a/gcc/config/pa/pa-protos.h
+++ b/gcc/config/pa/pa-protos.h
@@ -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));
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 0a5c4495457..540f8a7e4c8 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -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
diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h
index 223674634d4..536692b5405 100644
--- a/gcc/config/pa/pa.h
+++ b/gcc/config/pa/pa.h
@@ -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)
diff --git a/gcc/config/pa/som.h b/gcc/config/pa/som.h
index 073f79816de..06ee54b107b 100644
--- a/gcc/config/pa/som.h
+++ b/gcc/config/pa/som.h
@@ -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)
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index bbefa7e2a88..98fb376704f 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -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);
}
}
}
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 3058f671019..a9930eedd64 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index 0300deecb52..d1511f663eb 100644
--- a/gcc/cp/lex.c
+++ b/gcc/cp/lex.c
@@ -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>")
/* Return something to represent absolute declarators containing a *.
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index 036b1ce3c90..85e3650164b 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -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 ();
}
diff --git a/gcc/except.c b/gcc/except.c
index d3a0a3ca509..e7c5f7d2273 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -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);
diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c
index 2915b731f39..1b083818b15 100644
--- a/gcc/ggc-common.c
+++ b/gcc/ggc-common.c
@@ -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)
diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
index 8744129aaaf..2b64f45db53 100644
--- a/gcc/ggc-page.c
+++ b/gcc/ggc-page.c
@@ -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;
/* 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
diff --git a/gcc/ggc-simple.c b/gcc/ggc-simple.c
index 7822bb916f3..b5cab1bcb23 100644
--- a/gcc/ggc-simple.c
+++ b/gcc/ggc-simple.c
@@ -52,10 +52,6 @@
#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
diff --git a/gcc/ggc.h b/gcc/ggc.h
index 373026ce464..596c49b4989 100644
--- 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));
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index 156bcc15720..5fb49c0a9e7 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -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
diff --git a/gcc/java/jcf-parse.c b/gcc/java/jcf-parse.c
index 82c92ee1946..aa56811a630 100644
--- a/gcc/java/jcf-parse.c
+++ b/gcc/java/jcf-parse.c
@@ -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:
diff --git a/gcc/java/parse.y b/gcc/java/parse.y
index e422c85082a..a35e6dc22ec 100644
--- a/gcc/java/parse.y
+++ b/gcc/java/parse.y
@@ -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
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 5f046da9646..5ee436d7bf7 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -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));
}
}
diff --git a/gcc/profile.c b/gcc/profile.c
index b52b35257be..d60b2b2227c 100644
--- a/gcc/profile.c
+++ b/gcc/profile.c
@@ -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);
diff --git a/gcc/stmt.c b/gcc/stmt.c
index 82a390d1da1..4ec3fd52c89 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -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
index 00000000000..32381e01ebb
--- /dev/null
+++ b/gcc/stringpool.c
@@ -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);
+ }
+}
diff --git a/gcc/toplev.c b/gcc/toplev.c
index d25085a715c..592d5fc3604 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -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);
diff --git a/gcc/tree.c b/gcc/tree.c
index 7e820f559ce..28f791b0eba 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -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>")
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;
}
-
-#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);
-}
/* Return a newly constructed INTEGER_CST node whose constant value
is specified by the two ints LOW and HI.
diff --git a/gcc/tree.h b/gcc/tree.h
index a264df4fbdc..8f0737649aa 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -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));
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 0fc4ea8aa4a..b7d33b2f2b7 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -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