diff options
Diffstat (limited to 'gcc')
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 |