summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog520
-rw-r--r--gcc/Makefile.in48
-rw-r--r--gcc/ada/ChangeLog6
-rw-r--r--gcc/ada/ada-tree.h3
-rw-r--r--gcc/ada/gnat_rm.texi2
-rw-r--r--gcc/c-common.c10
-rw-r--r--gcc/c-common.h26
-rw-r--r--gcc/c-decl.c8
-rw-r--r--gcc/c-lex.c4
-rw-r--r--gcc/c-objc-common.c5
-rw-r--r--gcc/c-opts.c16
-rw-r--r--gcc/c-parse.in6
-rw-r--r--gcc/c-pch.c226
-rw-r--r--gcc/config/alpha/alpha.c46
-rw-r--r--gcc/config/darwin.c2
-rw-r--r--gcc/config/rs6000/rs6000.c88
-rw-r--r--gcc/config/rs6000/t-rs60005
-rw-r--r--gcc/cp/ChangeLog90
-rw-r--r--gcc/cp/Make-lang.in25
-rw-r--r--gcc/cp/call.c1
-rw-r--r--gcc/cp/class.c133
-rw-r--r--gcc/cp/cp-tree.h27
-rw-r--r--gcc/cp/decl.c3
-rw-r--r--gcc/cp/decl2.c4
-rw-r--r--gcc/cp/g++spec.c96
-rw-r--r--gcc/cp/init.c1
-rw-r--r--gcc/cp/lang-specs.h13
-rw-r--r--gcc/cp/lex.c6
-rw-r--r--gcc/cp/method.c5
-rw-r--r--gcc/cp/optimize.c1
-rw-r--r--gcc/cp/parser.c68
-rw-r--r--gcc/cp/pt.c1
-rw-r--r--gcc/cp/repo.c1
-rw-r--r--gcc/cp/search.c1
-rw-r--r--gcc/cp/semantics.c5
-rw-r--r--gcc/cp/tree.c1
-rw-r--r--gcc/cppfiles.c115
-rw-r--r--gcc/cpphash.h6
-rw-r--r--gcc/cpplib.c84
-rw-r--r--gcc/cpplib.h35
-rw-r--r--gcc/cpppch.c684
-rw-r--r--gcc/dbxout.c139
-rw-r--r--gcc/doc/cppopts.texi11
-rw-r--r--gcc/doc/gty.texi36
-rw-r--r--gcc/doc/invoke.texi134
-rw-r--r--gcc/doc/passes.texi44
-rw-r--r--gcc/dwarf2asm.c38
-rw-r--r--gcc/dwarf2out.c488
-rw-r--r--gcc/emit-rtl.c12
-rw-r--r--gcc/fold-const.c2
-rw-r--r--gcc/function.c2
-rw-r--r--gcc/gcc.c30
-rw-r--r--gcc/gengtype.c1500
-rw-r--r--gcc/ggc-common.c553
-rw-r--r--gcc/ggc-page.c258
-rw-r--r--gcc/ggc-simple.c85
-rw-r--r--gcc/ggc.h184
-rw-r--r--gcc/java/ChangeLog74
-rw-r--r--gcc/java/Make-lang.in8
-rw-r--r--gcc/java/config-lang.in2
-rw-r--r--gcc/java/constants.c64
-rw-r--r--gcc/java/gjavah.c1
-rw-r--r--gcc/java/java-tree.h10
-rw-r--r--gcc/java/jcf-dump.c1
-rw-r--r--gcc/java/jcf-parse.c49
-rw-r--r--gcc/java/jcf-reader.c18
-rw-r--r--gcc/java/jcf.h49
-rw-r--r--gcc/java/lex.c2
-rw-r--r--gcc/java/lex.h7
-rw-r--r--gcc/java/parse.h33
-rw-r--r--gcc/java/parse.y76
-rw-r--r--gcc/mkdeps.c74
-rw-r--r--gcc/mkdeps.h11
-rw-r--r--gcc/objc/objc-act.c1
-rw-r--r--gcc/optabs.h4
-rw-r--r--gcc/stringpool.c93
-rw-r--r--gcc/testsuite/ChangeLog84
-rw-r--r--gcc/testsuite/g++.dg/dg.exp1
-rw-r--r--gcc/testsuite/g++.dg/pch/empty.C5
-rw-r--r--gcc/testsuite/g++.dg/pch/empty.H0
-rw-r--r--gcc/testsuite/g++.dg/pch/pch.exp100
-rw-r--r--gcc/testsuite/g++.dg/pch/system-1.C7
-rw-r--r--gcc/testsuite/g++.dg/pch/system-1.H1
-rw-r--r--gcc/testsuite/gcc.dg/pch/common-1.c3
-rw-r--r--gcc/testsuite/gcc.dg/pch/common-1.h3
-rw-r--r--gcc/testsuite/gcc.dg/pch/cpp-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/pch/cpp-1.h1
-rw-r--r--gcc/testsuite/gcc.dg/pch/cpp-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/pch/cpp-2.h1
-rw-r--r--gcc/testsuite/gcc.dg/pch/decl-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/pch/decl-1.h1
-rw-r--r--gcc/testsuite/gcc.dg/pch/decl-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/pch/decl-2.h3
-rw-r--r--gcc/testsuite/gcc.dg/pch/decl-3.c11
-rw-r--r--gcc/testsuite/gcc.dg/pch/decl-3.h3
-rw-r--r--gcc/testsuite/gcc.dg/pch/decl-4.c9
-rw-r--r--gcc/testsuite/gcc.dg/pch/decl-4.h7
-rw-r--r--gcc/testsuite/gcc.dg/pch/decl-5.c2
-rw-r--r--gcc/testsuite/gcc.dg/pch/decl-5.h1
-rw-r--r--gcc/testsuite/gcc.dg/pch/empty.c8
-rw-r--r--gcc/testsuite/gcc.dg/pch/empty.h0
-rw-r--r--gcc/testsuite/gcc.dg/pch/except-1.c7
-rw-r--r--gcc/testsuite/gcc.dg/pch/except-1.h6
-rw-r--r--gcc/testsuite/gcc.dg/pch/global-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/pch/global-1.h1
-rw-r--r--gcc/testsuite/gcc.dg/pch/inline-1.c10
-rw-r--r--gcc/testsuite/gcc.dg/pch/inline-1.h5
-rw-r--r--gcc/testsuite/gcc.dg/pch/inline-2.c12
-rw-r--r--gcc/testsuite/gcc.dg/pch/inline-2.h5
-rw-r--r--gcc/testsuite/gcc.dg/pch/macro-1.c6
-rw-r--r--gcc/testsuite/gcc.dg/pch/macro-1.h2
-rw-r--r--gcc/testsuite/gcc.dg/pch/macro-2.c8
-rw-r--r--gcc/testsuite/gcc.dg/pch/macro-2.h2
-rw-r--r--gcc/testsuite/gcc.dg/pch/macro-3.c8
-rw-r--r--gcc/testsuite/gcc.dg/pch/macro-3.h2
-rw-r--r--gcc/testsuite/gcc.dg/pch/pch.exp100
-rw-r--r--gcc/testsuite/gcc.dg/pch/static-1.c6
-rw-r--r--gcc/testsuite/gcc.dg/pch/static-1.h5
-rw-r--r--gcc/testsuite/gcc.dg/pch/static-2.c6
-rw-r--r--gcc/testsuite/gcc.dg/pch/static-2.h5
-rw-r--r--gcc/testsuite/gcc.dg/pch/system-1.c6
-rw-r--r--gcc/testsuite/gcc.dg/pch/system-1.h2
-rw-r--r--gcc/testsuite/lib/g++-dg.exp4
-rw-r--r--gcc/testsuite/lib/gcc-dg.exp4
-rw-r--r--gcc/toplev.c2
-rw-r--r--gcc/tree.c4
-rw-r--r--gcc/tree.h8
-rw-r--r--gcc/varasm.c23
128 files changed, 5484 insertions, 1550 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index edae8315f57..2e2e1b2ac32 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,519 @@
+2003-01-09 Geoffrey Keating <geoffk@apple.com>
+
+ Merge from pch-branch:
+
+ 2003-01-06 Geoffrey Keating <geoffk@apple.com>
+
+ * ggc-page.c (ggc_pch_read): Update the statistics after a PCH
+ load.
+
+ 2002-12-24 Geoffrey Keating <geoffk@apple.com>
+
+ * cpplib.c (count_registered_pragmas): New function.
+ (save_registered_pragmas): New function.
+ (_cpp_save_pragma_names): New function.
+ (restore_registered_pragmas): New function.
+ (_cpp_restore_pragma_names): New function.
+ * cpphash.h (_cpp_save_pragma_names): Prototype.
+ (_cpp_restore_pragma_names): Likewise.
+ * cpppch.c (struct save_macro_item): Split from save_macro_data.
+ (struct save_macro_data): New field 'saved_pragmas'.
+ (save_macros): Update for changes to struct save_macro_data.
+ (cpp_prepare_state): Call _cpp_save_pragma_names, update
+ for changes to struct save_macro_data.
+ (cpp_read_state): Call _cpp_restore_pragma_names, update
+ for changes to struct save_macro_data.
+
+ * cpppch.c (cpp_read_state): Restore the hashtable references
+ in the cpp_reader.
+
+ * tree.h (built_in_decls): Mark for PCH.
+
+ * dbxout.c (lastfile): Don't mark for PCH.
+
+ * ggc.h: Document PCH calls into memory managers.
+
+ 2002-12-18 Geoffrey Keating <geoffk@apple.com>
+
+ * doc/invoke.texi (Precompiled Headers): Document the
+ directory form of PCH.
+ * cppfiles.c (validate_pch): New function.
+ (open_file_pch): Search suitably-named directories for PCH files.
+
+ 2002-12-14 Geoffrey Keating <geoffk@apple.com>
+
+ * doc/gty.texi (GTY Options): Document chain_next, chain_prev,
+ reorder options.
+ (Type Information): Mention that the information is also
+ used to implement PCH.
+ * doc/passes.texi (Passes): Improve documentation of
+ language-specific files.
+
+ 2002-12-11 Geoffrey Keating <geoffk@apple.com>
+
+ * gengtype.c (struct write_types_data): Add reorder_note_routine field.
+ (struct walk_type_data): Add reorder_fn field.
+ (walk_type): Process 'reorder' option.
+ (write_types_process_field): Reorder parameters to gt_pch_note_object,
+ call reorder_note_routine.
+ (write_func_for_structure): Reorder parameters to gt_pch_note_object.
+ (ggc_wtd): Update for change to struct write_types_data.
+ (pch_wtd): Likewise.
+ * ggc.h (gt_pch_note_object): Reorder parameters.
+ (gt_handle_reorder): New definition.
+ (gt_pch_note_reorder): New prototype.
+ * ggc-common.c (struct ptr_data): Add reorder_fn.
+ (gt_pch_note_object): Reorder parameters.
+ (gt_pch_note_reorder): New.
+ (gt_pch_save): Call reorder_fn.
+ * stringpool.c (gt_pch_n_S): Update for change to gt_pch_note_object.
+
+ * dbxout.c (cwd): Don't mark for PCH.
+
+ 2002-12-09 Geoffrey Keating <geoffk@apple.com>
+
+ * gengtype.c (finish_root_table): Fix some warnings.
+ (write_root): Handle TYPE_STRING.
+ * ggc.h (gt_ggc_m_S): Add prototype.
+ * stringpool.c (gt_ggc_m_S): New function.
+
+ 2002-11-30 Geoffrey Keating <geoffk@apple.com>
+
+ * dwarf2out.c (dw2_string_counter): New.
+ (AT_string_form): Use it.
+ (same_dw_val_p): Update for removal of hashtable.h hash tables.
+
+ 2002-11-22 Geoffrey Keating <geoffk@apple.com>
+
+ * dbxout.c: Include gt-dbxout.h.
+ (lastfile): Mark for PCH/GGC.
+ (cwd): Likewise.
+ (struct typeinfo): Likewise.
+ (typevec): Likewise.
+ (typevec_len): Likewise.
+ (next_type_number): Likewise.
+ (struct dbx_file): Likewise.
+ (current_file): Likewise.
+ (next_file_number): Likewise.
+ (dbxout_init): Allocate typevec, struct dbx_file with GGC.
+ (dbxout_start_source_file): Allocate struct dbx_file with GGC.
+ (dbxout_end_source_file): Don't free struct dbx_file.
+ (dbxout_type): Use GGC to allocate typevec.
+ * Makefile.in (dbxout.o): Depend on gt-dbxout.h, $(GGC_H).
+ (GTFILES): Add dbxout.c.
+ (gt-dbxout.h): New rule.
+
+ * Makefile.in (c-pch.o): Add debug.h as dependency.
+ * c-pch.c: Include debug.h.
+ (pch_init): Call start_source_file to keep nesting right.
+ (c_common_read_pch): Add orig_name parameter. Call
+ start_source_file debug hook. Call end_source_file debug hook.
+ * c-common.h (c_common_read_pch): Update prototype.
+ * cpplib.h (struct cpp_callbacks): Add fourth field to read_pch
+ callback.
+ * cppfiles.c (struct include_file): Add new field `header_name'.
+ (find_or_create_entry): Default it to `name'.
+ (open_file_pch): Set it to the original header file searched for.
+ (stack_include_file): Don't stack an empty buffer, just handle
+ PCH files immediately. Pass header_name field to read_pch callback.
+
+ 2002-11-19 Geoffrey Keating <geoffk@apple.com>
+
+ * function.c (funcdef_no): Mark to be saved in a PCH.
+
+ 2002-11-15 Geoffrey Keating <geoffk@apple.com>
+
+ * ggc-page.c (ggc_pch_read): Remove unused 'bmap_size'.
+
+ * cpppch.c (cpp_read_state): Correct size reallocated for 'defn'.
+
+ 2002-11-14 Geoffrey Keating <geoffk@apple.com>
+
+ * optabs.h (code_to_optab): Add GTY marker.
+
+ 2002-11-13 Geoffrey Keating <geoffk@apple.com>
+
+ * Makefile.in (GTFILES): Add cpplib.h.
+ * c-common.h (struct c_common_identifier): Don't skip 'node' field.
+ * c-decl.c (build_compound_literal): Don't use var_labelno.
+ * cpplib.h (struct cpp_hashnode): Use gengtype to mark.
+ * dwarf2asm.c (dw2_force_const_mem): Don't use const_labelno.
+ * varasm.c (const_labelno): Use gengtype to mark.
+ (var_labelno): Likewise.
+ (in_section): Likewise.
+ (in_named_name): Likewise.
+ (struct in_named_entry): Likewise.
+ (in_named_htab): Likewise.
+ (set_named_section_flags): Use GGC to allocate struct in_named_entry.
+ (init_varasm_once): Use GGC to allocate in_named_htab.
+ * config/darwin.c (current_pic_label_num): Mark for PCH.
+
+ 2002-11-11 Geoffrey Keating <geoffk@apple.com>
+
+ * ggc-simple.c (init_ggc_pch): New stub procedure.
+ (ggc_pch_count_object): Likewise.
+ (ggc_pch_total_size): Likewise.
+ (ggc_pch_this_base): Likewise.
+ (ggc_pch_alloc_object): Likewise.
+ (ggc_pch_prepare_write): Likewise.
+ (ggc_pch_write_object): Likewise
+ (ggc_pch_finish): Likewise.
+ (ggc_pch_read): Likewise.
+
+ 2002-11-08 Geoffrey Keating <geoffk@apple.com>
+
+ * c-pch.c (c_common_write_pch): Write the macro definitions after
+ the GCed data.
+ (c_common_read_pch): Call cpp_prepare_state. Restore the macro
+ definitions after the GCed data.
+ * cpplib.c (save_macros): New.
+ (reset_ht): New.
+ (cpp_write_pch_deps): Split out of cpp_write_pch.
+ (cpp_write_pch_state): Split out of cpp_write_pch.
+ (cpp_write_pch): Delete.
+ (struct save_macro_data): Delete.
+ (cpp_prepare_state): New.
+ (cpp_read_state): Erase and restore initial macro definitions.
+ * cpplib.h (struct save_macro_data): Forward-declare.
+ (cpp_write_pch_deps): Prototype.
+ (cpp_write_pch_state): Prototype.
+ (cpp_write_pch): Delete prototype.
+ (cpp_prepare_state): Prototype.
+ (cpp_read_state): Add fourth argument.
+
+ 2002-11-04 Geoffrey Keating <geoffk@apple.com>
+
+ * gengtype.c (adjust_field_rtx_def): Don't use skip on valid fields.
+ (write_array): Remove warning.
+
+ * gengtype.c (contains_scalar_p): New.
+ (finish_root_table): Add the table to all languages, even if it's
+ empty.
+ (write_roots): Output gt_pch_scalar_rtab.
+ * ggc-common.c (gt_pch_save): Write out scalars.
+ (gt_pch_restore): Read scalars back.
+
+ * ggc-page.c (OBJECTS_IN_PAGE): New macro.
+ (struct page_entry): Delete pch_page field.
+ (ggc_recalculate_in_use_p): Use OBJECTS_IN_PAGE.
+ (clear_marks): Likewise.
+ (sweep_pages): Likewise.
+ (poison_pages): Likewise.
+ (ggc_print_statistics): Likewise.
+ (ggc_pch_read): Don't free objects read from a PCH.
+ Properly set up in_use_p and page_tails.
+
+ 2002-10-25 Geoffrey Keating <geoffk@apple.com>
+
+ * gengtype.c (struct write_types_data): New.
+ (struct walk_type_data): Make `cookie' const; add extra
+ prev_val item; add `orig_s' field.
+ (walk_type): Update prev_val[3].
+ (write_types_process_field): New.
+ (write_func_for_structure): Take write_types_data structure.
+ (write_types): New.
+ (ggc_wtd): New.
+ (pch_wtd): New.
+ (write_types_local_process_field): New.
+ (gc_mark_process_field): Delete.
+ (write_local_func_for_structure): New.
+ (gc_mark_func_name): Delete.
+ (write_gc_types): Delete.
+ (write_local): New.
+ (finish_root_table): Don't include 'ggc_' in PFX.
+ (write_root): Rename from write_root. Fill pchw field of structures.
+ (write_array): New.
+ (write_roots): Rename from write_gc_roots. Split out to write_array.
+ Update to changes to other routines. Write gt_pch_cache_rtab table.
+ (main): Write PCH walking routines.
+ * ggc-common.c: Include toplev.h, sys/mman.h.
+ (ggc_mark_roots): For cache hashtables, also mark the hash table
+ and the array of entries.
+ (saving_htab): New.
+ (struct ptr_data): New.
+ (POINTER_HASH): New.
+ (gt_pch_note_object): New.
+ (saving_htab_hash): New.
+ (saving_htab_eq): New.
+ (struct traversal_state): New.
+ (call_count): New.
+ (call_alloc): New.
+ (compare_ptr_data): New.
+ (relocate_ptrs): New.
+ (write_pch_globals): New.
+ (struct mmap_info): New.
+ (gt_pch_save): New.
+ (gt_pch_restore): New.
+ * ggc-page.c (ROUND_UP_VALUE): New.
+ (ROUND_UP): New.
+ (struct page_entry): Add field `pch_page'.
+ (init_ggc): Use ROUND_UP.
+ (struct ggc_pch_data): Declare.
+ (init_ggc_pch): New.
+ (ggc_pch_count_object): New.
+ (ggc_pch_total_size): New.
+ (ggc_pch_this_base): New.
+ (ggc_pch_alloc_object): New.
+ (ggc_pch_prepare_write): New.
+ (ggc_pch_write_object): New.
+ (ggc_pch_finish): New.
+ (ggc_pch_read): New.
+ * ggc.h (gt_pointer_operator): New.
+ (gt_note_pointers): New.
+ (gt_pch_note_object): New prototype.
+ (gt_pointer_walker): New.
+ (struct ggc_root_tab): Use gt_pointer_walker, add `pchw' field.
+ (LAST_GGC_ROOT_TAB): Update.
+ (gt_pch_cache_rtab): Declare.
+ (gt_pch_scalar_rtab): Declare.
+ (struct ggc_cache_tab): Use gt_pointer_walker, add `pchw' field.
+ (LAST_GGC_CACHE_TAB): Update.
+ (gt_pch_save_stringpool): Declare.
+ (gt_pch_restore_stringpool): Declare.
+ (gt_pch_p_S): Declare.
+ (gt_pch_n_S): Declare.
+ (struct ggc_pch_data): Forward-declare.
+ (init_ggc_pch): Declare.
+ (ggc_pch_count_object): Declare.
+ (ggc_pch_total_size): Declare.
+ (ggc_pch_this_base): Declare.
+ (ggc_pch_alloc_object): Declare.
+ (ggc_pch_prepare_write): Declare.
+ (ggc_pch_write_object): Declare.
+ (ggc_pch_finish): Declare.
+ (ggc_pch_read): Declare.
+ (gt_pch_save): Declare.
+ (gt_pch_restore): Declare.
+ * fold-const.c (size_int_type_wide): Allocate size_htab using GGC.
+ * emit-rtl.c (init_emit_once): Allocate const_int_htab,
+ const_double_htab, mem_attrs_htab using GGC.
+ * c-pch.c: Include ggc.h.
+ (pch_init): Allow reading PCH file back.
+ (c_common_write_pch): Call gt_pch_save.
+ (c_common_read_pch): Call gt_pch_restore.
+ * c-parse.in (init_reswords): Delete now-untrue comment.
+ Allocate ridpointers using GGC.
+ * c-objc-common.c (c_objc_common_finish_file): Write PCH before
+ calling expand_deferred_fns.
+ * c-common.h (ridpointers): Mark for GTY machinery.
+ * Makefile.in (stringpool.o): Update dependencies.
+ (c-pch.o): Update dependencies.
+ (ggc-common.o): Update dependencies.
+ * stringpool.c: Include gt-stringpool.h.
+ (gt_pch_p_S): New.
+ (gt_pch_n_S): New.
+ (struct string_pool_data): New.
+ (spd): New.
+ (gt_pch_save_stringpool): New.
+ (gt_pch_restore_stringpool): New.
+ * tree.c (init_ttree): Make type_hash_table allocated using GC.
+
+ 2002-10-04 Geoffrey Keating <geoffk@apple.com>
+
+ * gengtype.c (adjust_field_rtx_def): Don't pass size_t to printf.
+ (output_mangled_typename): Don't pass size_t to printf.
+
+ * tree.h (union tree_type_symtab): Add tag to `address' field.
+ (union tree_decl_u2): Add tag to 'i' field.
+ * varasm.c (union rtx_const_un): Add tags to all fields.
+ * gengtype.c (struct walk_type_data): New.
+ (output_escaped_param): Take struct walk_type_data parameter.
+ (write_gc_structure_fields): Delete.
+ (walk_type): New.
+ (write_gc_marker_routine_for_structure): Delete.
+ (write_func_for_structure): New.
+ (gc_mark_process_field): New.
+ (gc_mark_func_name): New.
+ (gc_counter): Delete.
+ (write_gc_types): Use write_func_for_structure.
+ (write_gc_roots): Use walk_type.
+
+ 2002-10-02 Geoffrey Keating <geoffk@apple.com>
+
+ * ggc-common.c (ggc_mark_roots): Delete 'x'.
+ (ggc_splay_dont_free): Fix warning about unused 'x'.
+ (ggc_print_common_statistics): Remove warnings.
+
+ 2002-10-01 Mike Stump <mrs@apple.com>
+
+ * ggc-common.c (ggc_splay_alloc): Actually return the allocated area.
+ * gengtype.c (write_gc_structure_fields): Handle param[digit]_is.
+
+ 2002-09-01 Geoffrey Keating <geoffk@redhat.com>
+ Catherine Moore <clm@redhat.com>
+
+ * Makefile (c-pch.o): Update dependencies.
+ (LIBCPP_OBJS): Add cpppch.o.
+ (cpppch.o): New.
+ * c-common.c (c_common_init): Don't call pch_init here.
+ * c-common.h (c_common_read_pch): Update prototype.
+ * c-lex.c (c_common_parse_file): Call pch_init here.
+ * c-opts.c (COMMAND_LINE_OPTIONS): Add -Winvalid-pch, -fpch-deps.
+ (c_common_decode_option): Handle them.
+ * c-pch.c: Include c-pragma.h.
+ (save_asm_offset): Delete.
+ (pch_init): Move contents of save_asm_offset into here, call
+ cpp_save_state.
+ (c_common_write_pch): Call cpp_write_pch.
+ (c_common_valid_pch): Warn only when -Winvalid-pch. Call
+ cpp_valid_state.
+ (c_common_read_pch): Add NAME parameter. Call cpp_read_state.
+ * cppfiles.c (stack_include_file): Update for change to
+ parameters of cb.read_pch.
+ * cpphash.h (struct cpp_reader): Add `savedstate' field.
+ * cpplib.h (struct cpp_options): Add `warn_invalid_pch' and
+ `restore_pch_deps' fields.
+ (struct cpp_callbacks): Add NAME parameter to `read_pch'.
+ (cpp_save_state): Prototype.
+ (cpp_write_pch): Prototype.
+ (cpp_valid_state): Prototype.
+ (cpp_read_state): Prototype.
+ * cpppch.c: New file.
+ * flags.h (version_flag): Remove prototype.
+ * mkdeps.c (deps_save): New.
+ (deps_restore): New.
+ * mkdeps.h (deps_save): Prototype.
+ (deps_restore): Prototype.
+ * toplev.c (late_init_hook): Delete.
+ (version_flag): Make static again.
+ (compile_file): Don't call late_init_hook.
+ * toplev.h (late_init_hook): Delete.
+ * doc/cppopts.texi: Document -fpch-deps.
+ * doc/invoke.texi (Warning Options): Document -Winvalid-pch.
+
+ 2002-08-27 Geoffrey Keating <geoffk@redhat.com>
+
+ * c-pch.c (c_common_write_pch): Rename from c_write_pch, change
+ callers.
+ (c_common_valid_pch): Rename from c_valid_pch, change callers.
+ (c_common_read_pch): Rename from c_read_pch, change callers.
+
+ * c-opts.c (COMMAND_LINE_OPTIONS): Allow -output-pch= to have
+ a space between it and its argument.
+
+ 2002-08-24 Geoffrey Keating <geoffk@redhat.com>
+
+ * c-pch.c: New file.
+ * toplev.h (late_init_hook): Declare.
+ * toplev.c (late_init_hook): Define.
+ (version_flag): Make globally visible.
+ (compile_file): Call late_init_hook.
+ (init_asm_output): Make output file seekable.
+ * gcc.c (default_compilers): Update c-header rule.
+ * flags.h (version_flag): Declare.
+ * cpplib.h (struct cpp_callbacks): Add 'valid_pch' and 'read_pch'
+ fields.
+ * cppfiles.c (struct include_file): Add 'pch' field.
+ (INCLUDE_PCH_P): New.
+ (open_file_pch): New.
+ (stack_include_file): Handle PCH files specially.
+ (find_include_file): Call open_file_pch instead of open_file.
+ (_cpp_read_file): Explain why open_file is used instead of
+ open_file_pch.
+ * c-opts.c (c_common_decode_option): Correct OPT__output_pch case.
+ * c-objc-common.c (c_objc_common_finish_file): Call c_write_pch.
+ * c-lex.c (init_c_lex): Set valid_pch and read_pch fields
+ in cpplib callbacks.
+ * c-common.c (pch_file): Correct comment.
+ (allow_pch): Define.
+ (c_common_init): Call pch_init.
+ * c-common.h (allow_pch): Declare.
+ (pch_init): Declare.
+ (c_valid_pch): Declare.
+ (c_read_pch): Declare.
+ (c_write_pch): Declare.
+ * Makefile.in (c-pch.o): New.
+ (C_AND_OBJC_OBJS): Add c-pch.o.
+ * doc/invoke.texi (Precompiled Headers): Add index entries,
+ complete truncated paragraph.
+
+ 2002-08-17 Geoffrey Keating <geoffk@redhat.com>
+
+ * c-common.c: (pch_file): Define.
+ * c-common.h (pch_file): Declare.
+ * c-opts.c (COMMAND_LINE_OPTIONS): Add --output-pch=.
+ (missing_arg): Require --output-pch= to have an argument.
+ (c_common_decode_option): Handle --output-pch=.
+ * gcc.c: Document new %V.
+ (default_compilers): Handle compiling C header files.
+ (do_spec_1): Implement %V.
+ (main): Handle "gcc foo.h" without trying to run linker.
+ * doc/invoke.texi (Invoking GCC): Add new menu item for PCH.
+ (Overall Options): Document what the driver does with header files,
+ document new -x option possibilities.
+ (Invoking G++): More documentation for PCH.
+ (Precompiled Headers): New.
+
+ 2002-08-09 Geoffrey Keating <geoffk@redhat.com>
+
+ * ggc.h: Don't include varray.h. Rearrange functions to be more
+ organized.
+ (ggc_add_root): Delete.
+ (ggc_mark_rtx): Delete.
+ (ggc_mark_tree): Delete.
+ (struct ggc_statistics): Remove contents.
+ * ggc-common.c: Remove unneeded includes.
+ (struct ggc_root): Delete.
+ (roots): Delete.
+ (ggc_add_root): Delete.
+ (ggc_mark_roots): Don't mark `roots'. Call ggc_mark_stringpool.
+ (ggc_print_common_statistics): Remove most of the contents.
+ * Makefile.in (GGC_H): No longer uses varray.h.
+ (ggc-common.o): Update dependencies.
+ (c-parse.o): Add varray.h to dependencies.
+ (c-common.o): Add varray.h.
+ * stringpool.c (mark_ident): Use mangled name for tree marker routine.
+ (mark_ident_hash): Rename to ggc_mark_stringpool.
+ (init_stringpool): Don't use ggc_add_root.
+ * c-parse.in: Include varray.h.
+ * c-common.c: Include varray.h.
+ * objc/Make-lang.in (objc-act.o): Add varray.h.
+ * objc/objc-act.c: Include varray.h.
+
+ 2002-07-25 Geoffrey Keating <geoffk@redhat.com>
+
+ * dwarf2out.c (dw_cfi_oprnd2_desc): Fix ISO-only function definition.
+ (dw_cfi_oprnd1_desc): Likewise.
+
+ 2002-07-17 Geoffrey Keating <geoffk@redhat.com>
+
+ * config/alpha/alpha.c (struct alpha_links): Use gengtype to mark;
+ move out of ifdef.
+ (alpha_links): Use gengtype to mark; move out of ifdef.
+ (mark_alpha_links_node): Delete.
+ (mark_alpha_links): Delete.
+ (alpha_need_linkage): Use GGC to allocate splay tree, struct
+ alpha_links, strings. Don't use ggc_add_root.
+ * ggc-common.c (ggc_splay_alloc): New.
+ (ggc_splay_dont_free): New.
+ * ggc.h (ggc_mark_rtx): Update for changed name mangling.
+ (ggc_mark_tree): Likewise.
+ (splay_tree_new_ggc): New.
+ (ggc_splay_alloc): Declare.
+ (ggc_splay_dont_free): Declare.
+ * dwarf2asm.c: Include gt-dwarf2asm.h.
+ (mark_indirect_pool_entry): Delete.
+ (mark_indirect_pool): Delete.
+ (indirect_pool): Use gengtype to mark.
+ (dw2_force_const_mem): Don't use ggc_add_root.
+ * Makefile.in (dwarf2asm.o): Depend on gt-dwarf2asm.h.
+ (GTFILES): Add SPLAY_TREE_H, dwarf2asm.c.
+ (gt-dwarf2asm.h): Depend on s-gtype.
+
+ 2002-07-08 Geoffrey Keating <geoffk@redhat.com>
+
+ * tree.h (union tree_type_symtab): Mark `die' field.
+ * Makefile.in (dwarf2out.o): Update dependencies.
+ * dwarf2out.c: Use GGC to allocate all structures. Convert to htab_t
+ hash tables.
+ (dw_cfi_oprnd1_desc): New function.
+ (dw_cfi_oprnd2_desc): New function.
+ (indirect_string_alloc): Delete.
+ (debug_str_do_hash): New function.
+ (debug_str_eq): New function.
+ (mark_limbo_die_list): Delete.
+ (dwarf2out_init): Don't call ggc_add_root.
+
2003-01-09 Vladimir Makarov <vmakarov@redhat.com>
The following changes are merged from itanium-sched-branch:
@@ -438,10 +954,10 @@
the generated code.
(write_automata): Call the new function.
-
Thu Jan 9 22:47:38 CET 2003 Jan Hubicka <jh@suse.cz>
- * i386.md (unit, prefix_0f, memory attributes): Hanlde sseicvt correctly.
+ * i386.md (unit, prefix_0f, memory attributes): Hanlde sseicvt
+ correctly.
2003-01-09 Paolo Carlini <pcarlini@unitus.it>
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 5ffdce2a9fb..c48d41cc3a2 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -587,7 +587,7 @@ REGS_H = regs.h varray.h $(MACHMODE_H)
INTEGRATE_H = integrate.h varray.h
LOOP_H = loop.h varray.h bitmap.h
GCC_H = gcc.h version.h
-GGC_H = ggc.h varray.h gtype-desc.h
+GGC_H = ggc.h gtype-desc.h
TIMEVAR_H = timevar.h timevar.def
INSN_ATTR_H = insn-attr.h $(srcdir)/insn-addr.h $(srcdir)/varray.h
C_COMMON_H = c-common.h $(SPLAY_TREE_H) $(CPPLIB_H)
@@ -739,7 +739,7 @@ CXX_TARGET_OBJS=@cxx_target_objs@
# Language-specific object files for C and Objective C.
C_AND_OBJC_OBJS = attribs.o c-errors.o c-lex.o c-pragma.o c-decl.o c-typeck.o \
c-convert.o c-aux-info.o c-common.o c-opts.o c-format.o c-semantics.o \
- c-objc-common.o c-dump.o libcpp.a $(C_TARGET_OBJS)
+ c-objc-common.o c-dump.o c-pch.o libcpp.a $(C_TARGET_OBJS)
# Language-specific object files for C.
C_OBJS = c-parse.o c-lang.o c-pretty-print.o $(C_AND_OBJC_OBJS)
@@ -1175,7 +1175,7 @@ c-errors.o: c-errors.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(C_TREE_H) flags.h diagnostic.h $(TM_P_H)
c-parse.o : $(srcdir)/c-parse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(GGC_H) intl.h $(C_TREE_H) input.h flags.h toplev.h output.h $(CPPLIB_H) \
- gt-c-parse.h
+ varray.h gt-c-parse.h
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-c $(srcdir)/c-parse.c $(OUTPUT_OPTION)
@@ -1246,7 +1246,7 @@ tlink.o: tlink.c $(DEMANGLE_H) $(HASHTAB_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h
c-common.o : c-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(OBSTACK_H) $(C_COMMON_H) flags.h toplev.h output.h c-pragma.h $(RTL_H) \
$(GGC_H) $(EXPR_H) $(TM_P_H) builtin-types.def builtin-attrs.def $(TARGET_H) \
- diagnostic.h except.h gt-c-common.h real.h langhooks.h
+ diagnostic.h except.h gt-c-common.h real.h langhooks.h varray.h
c-pretty-print.o : c-pretty-print.c c-pretty-print.h pretty-print.h \
$(C_COMMON_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) real.h
@@ -1270,6 +1270,9 @@ c-semantics.o : c-semantics.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE
c-dump.o : c-dump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(C_TREE_H) tree-dump.h
+c-pch.o : c-pch.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(CPPLIB_H) $(TREE_H) \
+ c-common.h output.h toplev.h c-pragma.h $(GGC_H) debug.h
+
# Language-independent files.
DRIVER_DEFINES = \
@@ -1349,18 +1352,17 @@ gtype-desc.o: gtype-desc.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) varray.h
libfuncs.h debug.h $(GGC_H) bitmap.h $(BASIC_BLOCK_H) hard-reg-set.h \
ssa.h cselib.h insn-addr.h
-ggc-common.o: ggc-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
- flags.h $(GGC_H) varray.h $(HASHTAB_H) $(TM_P_H) langhooks.h \
- $(PARAMS_H)
+ggc-common.o: ggc-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(GGC_H) \
+ $(HASHTAB_H) toplev.h
ggc-simple.o: ggc-simple.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
flags.h $(GGC_H) varray.h $(TIMEVAR_H) $(TM_P_H) $(PARAMS_H)
ggc-page.o: ggc-page.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
- flags.h toplev.h $(GGC_H) varray.h $(TIMEVAR_H) $(TM_P_H)
+ flags.h toplev.h $(GGC_H) varray.h $(TIMEVAR_H) $(TM_P_H) $(PARAMS_H)
-stringpool.o: stringpool.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- $(OBSTACK_H) flags.h toplev.h $(GGC_H)
+stringpool.o: stringpool.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(TREE_H) $(GGC_H) gt-stringpool.h
hashtable.o: hashtable.c hashtable.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(OBSTACK_H)
@@ -1466,11 +1468,12 @@ optabs.o : optabs.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_
toplev.h $(GGC_H) real.h $(TM_P_H) except.h gt-optabs.h $(BASIC_BLOCK_H)
dbxout.o : dbxout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) \
flags.h $(REGS_H) debug.h $(TM_P_H) $(TARGET_H) function.h langhooks.h \
- insn-config.h reload.h gstab.h xcoffout.h output.h dbxout.h toplev.h
+ insn-config.h reload.h gstab.h xcoffout.h output.h dbxout.h toplev.h \
+ $(GGC_H) gt-dbxout.h
debug.o : debug.c debug.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H)
sdbout.o : sdbout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) \
flags.h function.h $(EXPR_H) output.h hard-reg-set.h $(REGS_H) real.h \
- insn-config.h xcoffout.h c-pragma.h ggc.h $(TARGET_H) \
+ insn-config.h xcoffout.h c-pragma.h $(GGC_H) $(TARGET_H) \
sdbout.h toplev.h $(TM_P_H) except.h debug.h langhooks.h gt-sdbout.h
dwarfout.o : dwarfout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(RTL_H) dwarf.h flags.h insn-config.h reload.h output.h toplev.h $(TM_P_H) \
@@ -1480,7 +1483,7 @@ dwarf2out.o : dwarf2out.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H)
hard-reg-set.h $(REGS_H) $(EXPR_H) libfuncs.h toplev.h dwarf2out.h varray.h \
$(GGC_H) except.h dwarf2asm.h $(TM_P_H) langhooks.h $(HASHTAB_H) gt-dwarf2out.h
dwarf2asm.o : dwarf2asm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) flags.h $(RTL_H) \
- $(TREE_H) output.h dwarf2asm.h $(TM_P_H) $(GGC_H)
+ $(TREE_H) output.h dwarf2asm.h $(TM_P_H) $(GGC_H) gt-dwarf2asm.h
vmsdbgout.o : vmsdbgout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(RTL_H) flags.h output.h vmsdbg.h debug.h langhooks.h function.h $(TARGET_H)
xcoffout.o : xcoffout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) \
@@ -1862,22 +1865,22 @@ s-preds: genpreds$(build_exeext) $(srcdir)/move-if-change
$(SHELL) $(srcdir)/move-if-change tmp-preds.h tm-preds.h
$(STAMP) s-preds
-GTFILES = $(srcdir)/location.h $(srcdir)/coretypes.h \
- $(host_xm_file_list) $(tm_file_list) $(HASHTAB_H) \
+GTFILES = $(srcdir)/location.h $(srcdir)/coretypes.h $(srcdir)/cpplib.h \
+ $(host_xm_file_list) $(tm_file_list) $(HASHTAB_H) $(SPLAY_TREE_H) \
$(srcdir)/bitmap.h $(srcdir)/function.h $(srcdir)/rtl.h $(srcdir)/optabs.h \
$(srcdir)/tree.h $(srcdir)/libfuncs.h $(srcdir)/hashtable.h $(srcdir)/real.h \
$(srcdir)/varray.h $(srcdir)/ssa.h $(srcdir)/insn-addr.h $(srcdir)/cselib.h \
+ $(srcdir)/basic-block.h $(srcdir)/location.h \
$(srcdir)/c-common.h $(srcdir)/c-tree.h \
- $(srcdir)/basic-block.h \
$(srcdir)/alias.c $(srcdir)/bitmap.c $(srcdir)/cselib.c \
- $(srcdir)/dwarf2out.c $(srcdir)/emit-rtl.c \
- $(srcdir)/except.c $(srcdir)/explow.c $(srcdir)/expr.c \
+ $(srcdir)/dbxout.c $(srcdir)/dwarf2out.c $(srcdir)/dwarf2asm.c \
+ $(srcdir)/emit-rtl.c $(srcdir)/except.c $(srcdir)/explow.c $(srcdir)/expr.c \
$(srcdir)/fold-const.c $(srcdir)/function.c \
$(srcdir)/gcse.c $(srcdir)/integrate.c $(srcdir)/lists.c $(srcdir)/optabs.c \
$(srcdir)/profile.c $(srcdir)/ra-build.c $(srcdir)/regclass.c \
$(srcdir)/reg-stack.c \
$(srcdir)/sdbout.c $(srcdir)/stmt.c $(srcdir)/stor-layout.c \
- $(srcdir)/tree.c $(srcdir)/varasm.c \
+ $(srcdir)/stringpool.c $(srcdir)/tree.c $(srcdir)/varasm.c \
$(out_file) \
@all_gtfiles@
@@ -1891,9 +1894,9 @@ gt-integrate.h gt-stmt.h gt-tree.h gt-varasm.h gt-emit-rtl.h : s-gtype; @true
gt-explow.h gt-stor-layout.h gt-regclass.h gt-lists.h : s-gtype; @true
gt-alias.h gt-cselib.h gt-fold-const.h gt-gcse.h gt-profile.h : s-gtype; @true
gt-expr.h gt-sdbout.h gt-optabs.h gt-bitmap.h gt-dwarf2out.h : s-gtype ; @true
-gt-ra-build.h gt-reg-stack.h : s-gtype ; @true
+gt-ra-build.h gt-reg-stack.h gt-dwarf2asm.h gt-dbxout.h : s-gtype ; @true
gt-c-common.h gt-c-decl.h gt-c-parse.h gt-c-pragma.h : s-gtype; @true
-gt-c-objc-common.h gtype-c.h gt-location.h : s-gtype ; @true
+gt-c-objc-common.h gtype-c.h gt-location.h gt-stringpool.h : s-gtype ; @true
gtyp-gen.h: Makefile
echo "/* This file is machine generated. Do not edit. */" > tmp-gtyp.h
@@ -2215,7 +2218,7 @@ PREPROCESSOR_DEFINES = \
LIBCPP_OBJS = cpplib.o cpplex.o cppmacro.o cppexp.o cppfiles.o cpptrad.o \
cpphash.o cpperror.o cppinit.o cppdefault.o cppmain.o \
- hashtable.o line-map.o mkdeps.o prefix.o mbchar.o
+ hashtable.o line-map.o mkdeps.o prefix.o mbchar.o cpppch.o
LIBCPP_DEPS = $(CPPLIB_H) cpphash.h line-map.h hashtable.h intl.h \
$(OBSTACK_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H)
@@ -2238,6 +2241,7 @@ cpphash.o: cpphash.c $(LIBCPP_DEPS)
cpptrad.o: cpptrad.c $(LIBCPP_DEPS)
cppfiles.o: cppfiles.c $(LIBCPP_DEPS) $(SPLAY_TREE_H) mkdeps.h
cppinit.o: cppinit.c $(LIBCPP_DEPS) cppdefault.h mkdeps.h prefix.h
+cpppch.o: cpppch.c $(LIBCPP_DEPS) mkdeps.h
cppdefault.o: cppdefault.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) cppdefault.h \
Makefile
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 6b435f5ddd1..0d06e9c725a 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,9 @@
+2003-01-09 Geoffrey Keating <geoffk@apple.com>
+
+ * gnat_rm.texi: Remove RCS version number.
+
+ * ada-tree.h (union lang_tree_node): Add chain_next option.
+
2003-01-09 Christian Cornelssen <ccorn@cs.tu-berlin.de>
* Make-lang.in (ada.install-info, ada.install-common,
diff --git a/gcc/ada/ada-tree.h b/gcc/ada/ada-tree.h
index 53087a7e700..b1904a4284d 100644
--- a/gcc/ada/ada-tree.h
+++ b/gcc/ada/ada-tree.h
@@ -43,7 +43,8 @@ struct tree_loop_id GTY(())
/* The language-specific tree. */
union lang_tree_node
- GTY((desc ("TREE_CODE (&%h.generic) == GNAT_LOOP_ID")))
+ GTY((desc ("TREE_CODE (&%h.generic) == GNAT_LOOP_ID"),
+ chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
{
union tree_node GTY ((tag ("0"),
desc ("tree_node_structure (&%h)")))
diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi
index dd43cf05c65..f9c78ce515e 100644
--- a/gcc/ada/gnat_rm.texi
+++ b/gcc/ada/gnat_rm.texi
@@ -8,8 +8,6 @@
@c o
@c G N A T _ RM o
@c o
-@c $Revision: 1.9 $
-@c o
@c Copyright (C) 1995-2002 Free Software Foundation o
@c o
@c o
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 12cacab3d55..84166c98da3 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -31,6 +31,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "c-pragma.h"
#include "rtl.h"
#include "ggc.h"
+#include "varray.h"
#include "expr.h"
#include "c-common.h"
#include "diagnostic.h"
@@ -190,11 +191,20 @@ enum c_language_kind c_language;
tree c_global_trees[CTI_MAX];
+/* Nonzero if we can read a PCH file now. */
+
+int allow_pch = 1;
+
/* Switches common to the C front ends. */
/* Nonzero if prepreprocessing only. */
int flag_preprocess_only;
+/* The file name to which we should write a precompiled header, or
+ NULL if no header will be written in this compile. */
+
+const char *pch_file;
+
/* Nonzero if an ISO standard was selected. It rejects macros in the
user's namespace. */
int flag_iso;
diff --git a/gcc/c-common.h b/gcc/c-common.h
index 4c60d29fdee..3e976621711 100644
--- a/gcc/c-common.h
+++ b/gcc/c-common.h
@@ -121,7 +121,7 @@ enum rid
/* The elements of `ridpointers' are identifier nodes for the reserved
type names and storage classes. It is indexed by a RID_... value. */
-extern tree *ridpointers;
+extern GTY ((length ("(int)RID_MAX"))) tree *ridpointers;
/* Standard named or nameless data types of the C compiler. */
@@ -177,7 +177,7 @@ enum c_tree_index
struct c_common_identifier GTY(())
{
struct tree_common common;
- struct cpp_hashnode GTY ((skip (""))) node;
+ struct cpp_hashnode node;
};
#define wchar_type_node c_global_trees[CTI_WCHAR_TYPE]
@@ -360,13 +360,24 @@ struct c_lang_decl GTY(()) {
extern c_language_kind c_language;
+/* Nonzero if we can read a PCH file now. */
+
+extern int allow_pch;
+
/* Switches common to the C front ends. */
/* Nonzero if prepreprocessing only. */
+
extern int flag_preprocess_only;
+/* The file name to which we should write a precompiled header, or
+ NULL if no header will be written in this compile. */
+
+extern const char *pch_file;
+
/* Nonzero if an ISO standard was selected. It rejects macros in the
user's namespace. */
+
extern int flag_iso;
/* Nonzero whenever Objective-C functionality is being used. */
@@ -374,6 +385,7 @@ extern int flag_objc;
/* Nonzero if -undef was given. It suppresses target built-in macros
and assertions. */
+
extern int flag_undef;
/* Nonzero means don't recognize the non-ANSI builtin functions. */
@@ -1253,4 +1265,14 @@ extern void dump_time_statistics PARAMS ((void));
extern int c_dump_tree PARAMS ((void *, tree));
+extern void pch_init PARAMS ((void));
+extern int c_common_valid_pch PARAMS ((cpp_reader *pfile,
+ const char *name,
+ int fd));
+extern void c_common_read_pch PARAMS ((cpp_reader *pfile,
+ const char *name,
+ int fd,
+ const char *orig));
+extern void c_common_write_pch PARAMS ((void));
+
#endif /* ! GCC_C_COMMON_H */
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index fde8c482e12..e3d07aab96d 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -3226,6 +3226,8 @@ clear_parm_order ()
current_binding_level->parm_order = NULL_TREE;
}
+static GTY(()) int compound_literal_number;
+
/* Build a COMPOUND_LITERAL_EXPR. TYPE is the type given in the compound
literal, which may be an incomplete array type completed by the
initializer; INIT is a CONSTRUCTOR that initializes the compound
@@ -3273,10 +3275,10 @@ build_compound_literal (type, init)
/* This decl needs a name for the assembler output. We also need
a unique suffix to be added to the name. */
char *name;
- extern int var_labelno;
- ASM_FORMAT_PRIVATE_NAME (name, "__compound_literal", var_labelno);
- var_labelno++;
+ ASM_FORMAT_PRIVATE_NAME (name, "__compound_literal",
+ compound_literal_number);
+ compound_literal_number++;
DECL_NAME (decl) = get_identifier (name);
DECL_DEFER_OUTPUT (decl) = 1;
DECL_COMDAT (decl) = 1;
diff --git a/gcc/c-lex.c b/gcc/c-lex.c
index 5507e6311d0..a689ccab004 100644
--- a/gcc/c-lex.c
+++ b/gcc/c-lex.c
@@ -124,6 +124,8 @@ init_c_lex (filename)
cb->ident = cb_ident;
cb->file_change = cb_file_change;
cb->def_pragma = cb_def_pragma;
+ cb->valid_pch = c_common_valid_pch;
+ cb->read_pch = c_common_read_pch;
/* Set the debug callbacks if we can use them. */
if (debug_info_level == DINFO_LEVEL_VERBOSE
@@ -158,6 +160,8 @@ c_common_parse_file (set_yydebug)
(*debug_hooks->start_source_file) (lineno, input_filename);
cpp_finish_options (parse_in);
+ pch_init();
+
yyparse ();
free_parser_stacks ();
}
diff --git a/gcc/c-objc-common.c b/gcc/c-objc-common.c
index 7d54d7ace4d..c91e635b410 100644
--- a/gcc/c-objc-common.c
+++ b/gcc/c-objc-common.c
@@ -1,5 +1,5 @@
/* Some code common to C and ObjC front ends.
- Copyright (C) 2001 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
@@ -358,6 +358,9 @@ finish_cdtor (body)
void
c_objc_common_finish_file ()
{
+ if (pch_file)
+ c_common_write_pch ();
+
expand_deferred_fns ();
if (static_ctors)
diff --git a/gcc/c-opts.c b/gcc/c-opts.c
index 85ed5f325aa..5270d625a20 100644
--- a/gcc/c-opts.c
+++ b/gcc/c-opts.c
@@ -112,6 +112,7 @@ static void sanitize_cpp_opts PARAMS ((void));
#define COMMAND_LINE_OPTIONS \
OPT("-help", CL_ALL, OPT__help) \
+ OPT("-output-pch=", CL_ALL | CL_ARG, OPT__output_pch) \
OPT("C", CL_ALL, OPT_C) \
OPT("CC", CL_ALL, OPT_CC) \
OPT("E", CL_ALL, OPT_E) \
@@ -154,6 +155,7 @@ static void sanitize_cpp_opts PARAMS ((void));
OPT("Wimplicit-function-declaration", CL_C, OPT_Wimplicit_function_decl) \
OPT("Wimplicit-int", CL_C, OPT_Wimplicit_int) \
OPT("Wimport", CL_ALL, OPT_Wimport) \
+ OPT("Winvalid-pch", CL_ALL, OPT_Winvalid_pch) \
OPT("Wlong-long", CL_ALL, OPT_Wlong_long) \
OPT("Wmain", CL_C, OPT_Wmain) \
OPT("Wmissing-braces", CL_ALL, OPT_Wmissing_braces) \
@@ -231,6 +233,7 @@ static void sanitize_cpp_opts PARAMS ((void));
OPT("fnonnull-objects", CL_CXX, OPT_fnonnull_objects) \
OPT("foperator-names", CL_CXX, OPT_foperator_names) \
OPT("foptional-diags", CL_CXX, OPT_foptional_diags) \
+ OPT("fpch-deps", CL_ALL, OPT_fpch_deps) \
OPT("fpermissive", CL_CXX, OPT_fpermissive) \
OPT("fpreprocessed", CL_ALL, OPT_fpreprocessed) \
OPT("frepo", CL_CXX, OPT_frepo) \
@@ -343,6 +346,7 @@ missing_arg (opt_index)
switch (cl_options[opt_index].opt_code)
{
+ case OPT__output_pch:
case OPT_Wformat_eq:
case OPT_d:
case OPT_fabi_version:
@@ -627,6 +631,10 @@ c_common_decode_option (argc, argv)
print_help ();
break;
+ case OPT__output_pch:
+ pch_file = arg;
+ break;
+
case OPT_C:
cpp_opts->discard_comments = 0;
break;
@@ -832,6 +840,10 @@ c_common_decode_option (argc, argv)
cpp_opts->warn_import = on;
break;
+ case OPT_Winvalid_pch:
+ cpp_opts->warn_invalid_pch = on;
+ break;
+
case OPT_Wlong_long:
warn_long_long = on;
break;
@@ -1178,6 +1190,10 @@ c_common_decode_option (argc, argv)
flag_optional_diags = on;
break;
+ case OPT_fpch_deps:
+ cpp_opts->restore_pch_deps = on;
+ break;
+
case OPT_fpermissive:
flag_permissive = on;
break;
diff --git a/gcc/c-parse.in b/gcc/c-parse.in
index 70dfe905dfc..72ca4fe287b 100644
--- a/gcc/c-parse.in
+++ b/gcc/c-parse.in
@@ -48,6 +48,7 @@ end ifc
#include "c-pragma.h" /* For YYDEBUG definition, and parse_in. */
#include "c-tree.h"
#include "flags.h"
+#include "varray.h"
#include "output.h"
#include "toplev.h"
#include "ggc.h"
@@ -3555,10 +3556,7 @@ init_reswords ()
if (!flag_objc)
mask |= D_OBJC;
- /* It is not necessary to register ridpointers as a GC root, because
- all the trees it points to are permanently interned in the
- get_identifier hash anyway. */
- ridpointers = (tree *) xcalloc ((int) RID_MAX, sizeof (tree));
+ ridpointers = (tree *) ggc_calloc ((int) RID_MAX, sizeof (tree));
for (i = 0; i < N_reswords; i++)
{
/* If a keyword is disabled, do not enter it into the table
diff --git a/gcc/c-pch.c b/gcc/c-pch.c
new file mode 100644
index 00000000000..616e002a828
--- /dev/null
+++ b/gcc/c-pch.c
@@ -0,0 +1,226 @@
+/* Precompiled header implementation for the C languages.
+ Copyright (C) 2000, 2002 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. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "cpplib.h"
+#include "tree.h"
+#include "c-common.h"
+#include "output.h"
+#include "toplev.h"
+#include "debug.h"
+#include "c-pragma.h"
+#include "ggc.h"
+
+struct c_pch_header
+{
+ unsigned long asm_size;
+};
+
+static const char pch_ident[8] = "gpchC010";
+
+static FILE *pch_outfile;
+
+extern char *asm_file_name;
+static off_t asm_file_startpos;
+
+void
+pch_init ()
+{
+ FILE *f;
+
+ if (pch_file)
+ {
+ /* We're precompiling a header file, so when it's actually used,
+ it'll be at least one level deep. */
+ (*debug_hooks->start_source_file) (lineno, input_filename);
+
+ f = fopen (pch_file, "w+b");
+ if (f == NULL)
+ fatal_io_error ("can't open %s", pch_file);
+ pch_outfile = f;
+
+ if (fwrite (pch_ident, sizeof (pch_ident), 1, f) != 1)
+ fatal_io_error ("can't write to %s", pch_file);
+
+ /* We need to be able to re-read the output. */
+ /* The driver always provides a valid -o option. */
+ if (asm_file_name == NULL
+ || strcmp (asm_file_name, "-") == 0)
+ fatal_error ("`%s' is not a valid output file", asm_file_name);
+
+ asm_file_startpos = ftello (asm_out_file);
+
+ cpp_save_state (parse_in, f);
+ }
+}
+
+void
+c_common_write_pch ()
+{
+ char *buf;
+ off_t asm_file_end;
+ off_t written;
+ struct c_pch_header h;
+
+ cpp_write_pch_deps (parse_in, pch_outfile);
+
+ asm_file_end = ftello (asm_out_file);
+ h.asm_size = asm_file_end - asm_file_startpos;
+
+ if (fwrite (&h, sizeof (h), 1, pch_outfile) != 1)
+ fatal_io_error ("can't write %s", pch_file);
+
+ buf = xmalloc (16384);
+ fflush (asm_out_file);
+
+ if (fseeko (asm_out_file, asm_file_startpos, SEEK_SET) != 0)
+ fatal_io_error ("can't seek in %s", asm_file_name);
+
+ for (written = asm_file_startpos; written < asm_file_end; )
+ {
+ off_t size = asm_file_end - written;
+ if (size > 16384)
+ size = 16384;
+ if (fread (buf, size, 1, asm_out_file) != 1)
+ fatal_io_error ("can't read %s", asm_file_name);
+ if (fwrite (buf, size, 1, pch_outfile) != 1)
+ fatal_io_error ("can't write %s", pch_file);
+ written += size;
+ }
+ free (buf);
+
+ gt_pch_save (pch_outfile);
+ cpp_write_pch_state (parse_in, pch_outfile);
+
+ fclose (pch_outfile);
+}
+
+int
+c_common_valid_pch (pfile, name, fd)
+ cpp_reader *pfile;
+ const char *name;
+ int fd;
+{
+ int sizeread;
+ int result;
+ char ident[sizeof (pch_ident)];
+
+ if (! allow_pch)
+ return 2;
+
+ /* Perform a quick test of whether this is a valid
+ precompiled header for C. */
+
+ sizeread = read (fd, ident, sizeof (pch_ident));
+ if (sizeread == -1)
+ {
+ fatal_io_error ("can't read %s", name);
+ return 2;
+ }
+ else if (sizeread != sizeof (pch_ident))
+ return 2;
+
+ if (memcmp (ident, pch_ident, sizeof (pch_ident)) != 0)
+ {
+ if (cpp_get_options (pfile)->warn_invalid_pch)
+ {
+ if (memcmp (ident, pch_ident, 5) == 0)
+ /* It's a PCH, for the right language, but has the wrong version.
+ */
+ cpp_error (pfile, DL_WARNING,
+ "%s: not compatible with this GCC version", name);
+ else if (memcmp (ident, pch_ident, 4) == 0)
+ /* It's a PCH for the wrong language. */
+ cpp_error (pfile, DL_WARNING, "%s: not for C language", name);
+ else
+ /* Not any kind of PCH. */
+ cpp_error (pfile, DL_WARNING, "%s: not a PCH file", name);
+ }
+ return 2;
+ }
+
+ /* Check the preprocessor macros are the same as when the PCH was
+ generated. */
+
+ result = cpp_valid_state (pfile, name, fd);
+ if (result == -1)
+ return 2;
+ else
+ return result == 0;
+}
+
+void
+c_common_read_pch (pfile, name, fd, orig_name)
+ cpp_reader *pfile;
+ const char *name;
+ int fd;
+ const char *orig_name;
+{
+ FILE *f;
+ struct c_pch_header h;
+ char *buf;
+ unsigned long written;
+ struct save_macro_data *smd;
+
+ /* Before we wrote the file, we started a source file, so we have to start
+ one here to match. */
+ (*debug_hooks->start_source_file) (lineno, orig_name);
+
+ f = fdopen (fd, "rb");
+ if (f == NULL)
+ {
+ cpp_errno (pfile, DL_ERROR, "calling fdopen");
+ return;
+ }
+
+ allow_pch = 0;
+
+ if (fread (&h, sizeof (h), 1, f) != 1)
+ {
+ cpp_errno (pfile, DL_ERROR, "reading");
+ return;
+ }
+
+ buf = xmalloc (16384);
+ for (written = 0; written < h.asm_size; )
+ {
+ off_t size = h.asm_size - written;
+ if (size > 16384)
+ size = 16384;
+ if (fread (buf, size, 1, f) != 1
+ || fwrite (buf, size, 1, asm_out_file) != 1)
+ cpp_errno (pfile, DL_ERROR, "reading");
+ written += size;
+ }
+ free (buf);
+
+ cpp_prepare_state (pfile, &smd);
+
+ gt_pch_restore (f);
+
+ if (cpp_read_state (pfile, name, f, smd) != 0)
+ return;
+
+ fclose (f);
+
+ (*debug_hooks->end_source_file) (lineno);
+}
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index ce0810d0d26..dbbf1103dea 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -50,6 +50,7 @@ Boston, MA 02111-1307, USA. */
#include "target-def.h"
#include "debug.h"
#include "langhooks.h"
+#include <splay-tree.h>
/* Specify which cpu to schedule for. */
@@ -9023,6 +9024,20 @@ alpha_elf_select_rtx_section (mode, x, align)
#endif /* OBJECT_FORMAT_ELF */
+/* Structure to collect function names for final output
+ in link section. */
+
+enum links_kind {KIND_UNUSED, KIND_LOCAL, KIND_EXTERN};
+
+struct alpha_links GTY(())
+{
+ rtx linkage;
+ enum links_kind kind;
+};
+
+static GTY ((param1_is (char *), param2_is (struct alpha_links *)))
+ splay_tree alpha_links;
+
#if TARGET_ABI_OPEN_VMS
/* Return the VMS argument type corresponding to MODE. */
@@ -9058,26 +9073,6 @@ alpha_arg_info_reg_val (cum)
return GEN_INT (regval);
}
-/* Protect alpha_links from garbage collection. */
-
-static int
-mark_alpha_links_node (node, data)
- splay_tree_node node;
- void *data ATTRIBUTE_UNUSED;
-{
- struct alpha_links *links = (struct alpha_links *) node->value;
- ggc_mark_rtx (links->linkage);
- return 0;
-}
-
-static void
-mark_alpha_links (ptr)
- void *ptr;
-{
- splay_tree tree = *(splay_tree *) ptr;
- splay_tree_foreach (tree, mark_alpha_links_node, NULL);
-}
-
/* Make (or fake) .linkage entry for function call.
IS_LOCAL is 0 if name is used in call, 1 if name is used in definition.
@@ -9139,16 +9134,11 @@ alpha_need_linkage (name, is_local)
}
else
{
- alpha_links_tree = splay_tree_new
- ((splay_tree_compare_fn) strcmp,
- (splay_tree_delete_key_fn) free,
- (splay_tree_delete_key_fn) free);
-
- ggc_add_root (&alpha_links_tree, 1, 1, mark_alpha_links);
+ alpha_links = splay_tree_new_ggc ((splay_tree_compare_fn) strcmp);
}
- al = (struct alpha_links *) xmalloc (sizeof (struct alpha_links));
- name = xstrdup (name);
+ al = (struct alpha_links *) ggc_alloc (sizeof (struct alpha_links));
+ name = ggc_strdup (name);
/* Assume external if no definition. */
al->lkind = (is_local ? KIND_UNUSED : KIND_EXTERN);
diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c
index a7dfe59bec6..bce6d11e132 100644
--- a/gcc/config/darwin.c
+++ b/gcc/config/darwin.c
@@ -223,7 +223,7 @@ machopic_define_name (name)
static char function_base[32];
-static int current_pic_label_num;
+static GTY(()) int current_pic_label_num;
const char *
machopic_function_base_name ()
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 6112737d5b1..7880cd5c9f8 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -168,7 +168,6 @@ struct builtin_description
};
static bool rs6000_function_ok_for_sibcall PARAMS ((tree, tree));
-static void rs6000_add_gc_roots PARAMS ((void));
static int num_insns_constant_wide PARAMS ((HOST_WIDE_INT));
static void validate_condition_mode
PARAMS ((enum rtx_code, enum machine_mode));
@@ -183,8 +182,6 @@ static void rs6000_emit_allocate_stack PARAMS ((HOST_WIDE_INT, int));
static unsigned rs6000_hash_constant PARAMS ((rtx));
static unsigned toc_hash_function PARAMS ((const void *));
static int toc_hash_eq PARAMS ((const void *, const void *));
-static int toc_hash_mark_entry PARAMS ((void **, void *));
-static void toc_hash_mark_table PARAMS ((void *));
static int constant_pool_expr_1 PARAMS ((rtx, int *, int *));
static struct machine_function * rs6000_init_machine_status PARAMS ((void));
static bool rs6000_assemble_integer PARAMS ((rtx, unsigned int, int));
@@ -267,6 +264,19 @@ static void is_altivec_return_reg PARAMS ((rtx, void *));
static rtx generate_set_vrsave PARAMS ((rtx, rs6000_stack_t *, int));
static void altivec_frame_fixup PARAMS ((rtx, rtx, HOST_WIDE_INT));
static int easy_vector_constant PARAMS ((rtx));
+
+/* Hash table stuff for keeping track of TOC entries. */
+
+struct toc_hash_struct GTY(())
+{
+ /* `key' will satisfy CONSTANT_P; in fact, it will satisfy
+ ASM_OUTPUT_SPECIAL_POOL_ENTRY_P. */
+ rtx key;
+ enum machine_mode key_mode;
+ int labelno;
+};
+
+static GTY ((param_is (struct toc_hash_struct))) htab_t toc_hash_table;
/* Default register names. */
char rs6000_reg_names[][8] =
@@ -708,9 +718,6 @@ rs6000_override_options (default_cpu)
&& (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN))
real_format_for_mode[TFmode - QFmode] = &ibm_extended_format;
- /* Register global variables with the garbage collector. */
- rs6000_add_gc_roots ();
-
/* Allocate an alias set for register saves & restores from stack. */
rs6000_sr_alias_set = new_alias_set ();
@@ -11457,19 +11464,6 @@ rs6000_output_mi_thunk (file, thunk_fndecl, delta, vcall_offset, function)
*/
-/* Hash table stuff for keeping track of TOC entries. */
-
-struct toc_hash_struct
-{
- /* `key' will satisfy CONSTANT_P; in fact, it will satisfy
- ASM_OUTPUT_SPECIAL_POOL_ENTRY_P. */
- rtx key;
- enum machine_mode key_mode;
- int labelno;
-};
-
-static htab_t toc_hash_table;
-
/* Hash functions for the hash table. */
static unsigned
@@ -11570,39 +11564,6 @@ toc_hash_eq (h1, h2)
return rtx_equal_p (r1, r2);
}
-/* Mark the hash table-entry HASH_ENTRY. */
-
-static int
-toc_hash_mark_entry (hash_slot, unused)
- void ** hash_slot;
- void * unused ATTRIBUTE_UNUSED;
-{
- const struct toc_hash_struct * hash_entry =
- *(const struct toc_hash_struct **) hash_slot;
- rtx r = hash_entry->key;
- ggc_set_mark (hash_entry);
- /* For CODE_LABELS, we don't want to drag in the whole insn chain... */
- if (GET_CODE (r) == LABEL_REF)
- {
- ggc_set_mark (r);
- ggc_set_mark (XEXP (r, 0));
- }
- else
- ggc_mark_rtx (r);
- return 1;
-}
-
-/* Mark all the elements of the TOC hash-table *HT. */
-
-static void
-toc_hash_mark_table (vht)
- void *vht;
-{
- htab_t *ht = vht;
-
- htab_traverse (*ht, toc_hash_mark_entry, (void *)0);
-}
-
/* These are the names given by the C++ front-end to vtables, and
vtable-like objects. Ideally, this logic should not be here;
instead, there should be some programmatic way of inquiring as
@@ -11656,12 +11617,19 @@ output_toc (file, x, labelno, mode)
/* When the linker won't eliminate them, don't output duplicate
TOC entries (this happens on AIX if there is any kind of TOC,
- and on SVR4 under -fPIC or -mrelocatable). */
- if (TARGET_TOC)
+ and on SVR4 under -fPIC or -mrelocatable). Don't do this for
+ CODE_LABELs. */
+ if (TARGET_TOC && GET_CODE (x) != LABEL_REF)
{
struct toc_hash_struct *h;
void * * found;
+ /* Create toc_hash_table. This can't be done at OVERRIDE_OPTIONS
+ time because GGC is not initialised at that point. */
+ if (toc_hash_table == NULL)
+ toc_hash_table = htab_create_ggc (1021, toc_hash_function,
+ toc_hash_eq, NULL);
+
h = ggc_alloc (sizeof (*h));
h->key = x;
h->key_mode = mode;
@@ -12685,17 +12653,6 @@ rs6000_fatal_bad_address (op)
fatal_insn ("bad address", op);
}
-/* Called to register all of our global variables with the garbage
- collector. */
-
-static void
-rs6000_add_gc_roots ()
-{
- toc_hash_table = htab_create (1021, toc_hash_function, toc_hash_eq, NULL);
- ggc_add_root (&toc_hash_table, 1, sizeof (toc_hash_table),
- toc_hash_mark_table);
-}
-
#if TARGET_MACHO
#if 0
@@ -13312,3 +13269,4 @@ rs6000_memory_move_cost (mode, class, in)
return 4 + rs6000_register_move_cost (mode, class, GENERAL_REGS);
}
+#include "gt-rs6000.h"
diff --git a/gcc/config/rs6000/t-rs6000 b/gcc/config/rs6000/t-rs6000
index 805e15d4e82..c2a7848711b 100644
--- a/gcc/config/rs6000/t-rs6000
+++ b/gcc/config/rs6000/t-rs6000
@@ -1,14 +1,17 @@
# General rules that all rs6000/ targets must have.
+gt-rs6000.h: s-gtype ; @true
+
rs6000.o: $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(RTL_H) $(REGS_H) hard-reg-set.h \
real.h insn-config.h conditions.h insn-attr.h flags.h $(RECOG_H) \
$(OBSTACK_H) $(TREE_H) $(EXPR_H) $(OPTABS_H) except.h function.h \
output.h $(BASIC_BLOCK_H) $(INTEGRATE_H) toplev.h $(GGC_H) $(HASHTAB_H) \
- $(TM_P_H) $(TARGET_H) $(TARGET_DEF_H) langhooks.h reload.h
+ $(TM_P_H) $(TARGET_H) $(TARGET_DEF_H) langhooks.h reload.h gt-rs6000.h
rs6000-c.o: $(srcdir)/config/rs6000/rs6000-c.c \
$(srcdir)/config/rs6000/rs6000-protos.h \
$(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(CPPLIB_H) \
$(TM_P_H) c-pragma.h errors.h coretypes.h $(TM_H)
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/rs6000/rs6000-c.c
+
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 2970abba965..fb530434027 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,93 @@
+2003-01-09 Geoffrey Keating <geoffk@apple.com>
+
+ Merge from pch-branch:
+
+ 2003-01-09 Geoffrey Keating <geoffk@apple.com>
+
+ Merge to tag pch-merge-20030102:
+
+ * semantics.c (finish_translation_unit): Don't call finish_file.
+ * parser.c: Don't include ggc.h.
+ (cp_lexer_new_main): Rename from cp_lexer_new, only create main lexer,
+ read first token here. Don't allow PCH files after the first
+ token is read.
+ (cp_lexer_new_from_tokens): Duplicate functionality from cp_lexer_new.
+ (cp_lexer_get_preprocessor_token): Allow LEXER to be NULL.
+ (cp_parser_new): Call cp_lexer_new_main before allocating GCed memory.
+ (cp_parser_late_parsing_for_member): Don't duplicate call to
+ cp_lexer_set_source_position_from_token.
+ (cp_parser_late_parsing_default_args): Likewise.
+ (yyparse): Call finish_file after clearing the_parser.
+
+ 2002-12-11 Geoffrey Keating <geoffk@apple.com>
+
+ * Make-lang.in: Remove $(GGC_H) from all dependencies.
+ (CXX_TREE_H): Add $(GGC_H).
+ * class.c: Don't include ggc.h.
+ (field_decl_cmp): Make parameters be 'const void *' to match qsort.
+ (method_name_cmp): Likewise.
+ (resort_data): New variable.
+ (resort_field_decl_cmp): New.
+ (resort_method_name_cmp): New.
+ (resort_sorted_fields): New.
+ (resort_type_method_vec): New.
+ (finish_struct_methods): Delete cast.
+ (finish_struct_1): Delete cast.
+ * cp-tree.h: Include ggc.h.
+ (struct lang_type_class): Add reorder attribute to field `methods'.
+ (union lang_decl_u3): Add reorder attribute to field `sorted_fields'.
+ (resort_sorted_fields): New prototype.
+ (resort_type_method_vec): New prototype.
+ * call.c: Don't include ggc.h.
+ * decl.c: Likewise.
+ * decl2.c: Likewise.
+ * init.c: Likewise.
+ * lex.c: Likewise.
+ * method.c: Likewise.
+ * optimize.c: Likewise.
+ * parse.y: Likewise.
+ * pt.c: Likewise.
+ * repo.c: Likewise.
+ * search.c: Likewise.
+ * semantics.c: Likewise.
+ * spew.c: Likewise.
+ * tree.c: Likewise.
+
+ * lang-specs.h: Remove comment.
+
+ 2002-12-03 Geoffrey Keating <geoffk@apple.com>
+
+ * cp-tree.h (struct operator_name_info_t): Mark for GTY machinery.
+ (operator_name_info): Mark to be saved for PCH, specify size.
+ (assignment_operator_name_info): Likewise.
+
+ 2002-11-19 Geoffrey Keating <geoffk@apple.com>
+
+ * decl.c (anon_cnt): Mark to be saved for PCH.
+
+ 2002-10-25 Geoffrey Keating <geoffk@apple.com>
+
+ * lex.c (init_reswords): Delete now-untrue comment.
+ Allocate ridpointers using GGC.
+
+ 2002-10-04 Geoffrey Keating <geoffk@apple.com>
+
+ * cp-tree.h (union lang_decl_u2): Add tags to all fields.
+
+ * g++spec.c (lang_specific_driver): Don't include standard
+ libraries in `added'.
+
+ 2002-08-27 Geoffrey Keating <geoffk@redhat.com>
+
+ * decl2.c (finish_file): Call c_common_write_pch.
+ * Make-lang.in (CXX_C_OBJS): Add c-pch.o.
+
+ 2002-08-17 Geoffrey Keating <geoffk@redhat.com>
+
+ * g++spec.c (lang_specific_driver): Treat .h files as C++ header
+ files when using g++.
+ * lang-specs.h: Handle compiling C++ header files.
+
2003-01-09 Jakub Jelinek <jakub@redhat.com>
* decl.c (start_decl): Only check DECL_THREAD_LOCAL for VAR_DECLs.
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index b54e3ba678f..347b71a906a 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -1,5 +1,5 @@
# Top level -*- makefile -*- fragment for GNU C++.
-# Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002
+# Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003
# Free Software Foundation, Inc.
#This file is part of GCC.
@@ -79,7 +79,7 @@ g++-cross$(exeext): g++$(exeext)
# The compiler itself.
# Shared with C front end:
CXX_C_OBJS = attribs.o c-common.o c-format.o c-pragma.o c-semantics.o c-lex.o \
- c-dump.o $(CXX_TARGET_OBJS) c-pretty-print.o c-opts.o
+ c-dump.o $(CXX_TARGET_OBJS) c-pretty-print.o c-opts.o c-pch.o
# Language-specific object files.
CXX_OBJS = cp/call.o cp/decl.o cp/expr.o cp/pt.o cp/typeck2.o \
@@ -210,34 +210,35 @@ c++.stage4: stage4-start
# .o: .h dependencies.
CXX_TREE_H = $(TREE_H) cp/cp-tree.h c-common.h cp/cp-tree.def c-common.def \
function.h varray.h $(SYSTEM_H) coretypes.h $(CONFIG_H) $(TARGET_H) \
+ $(GGC_H) \
$(srcdir)/../include/hashtab.h $(srcdir)/../include/splay-tree.h
cp/lex.o: cp/lex.c $(CXX_TREE_H) $(TM_H) flags.h cp/lex.h \
- c-pragma.h toplev.h output.h mbchar.h $(GGC_H) input.h diagnostic.h \
+ c-pragma.h toplev.h output.h mbchar.h input.h diagnostic.h \
cp/operators.def $(TM_P_H)
cp/cp-lang.o: cp/cp-lang.c $(CXX_TREE_H) $(TM_H) toplev.h langhooks.h \
$(LANGHOOKS_DEF_H) c-common.h
cp/decl.o: cp/decl.c $(CXX_TREE_H) $(TM_H) flags.h cp/lex.h cp/decl.h stack.h \
- output.h $(EXPR_H) except.h toplev.h $(HASHTAB_H) $(GGC_H) $(RTL_H) \
+ output.h $(EXPR_H) except.h toplev.h $(HASHTAB_H) $(RTL_H) \
cp/operators.def $(TM_P_H) tree-inline.h diagnostic.h c-pragma.h \
debug.h gt-cp-decl.h gtype-cp.h
cp/decl2.o: cp/decl2.c $(CXX_TREE_H) $(TM_H) flags.h cp/lex.h cp/decl.h $(EXPR_H) \
- output.h except.h toplev.h $(GGC_H) $(RTL_H) c-common.h gt-cp-decl2.h
+ output.h except.h toplev.h $(RTL_H) c-common.h gt-cp-decl2.h
cp/typeck2.o: cp/typeck2.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h output.h $(TM_P_H) \
diagnostic.h
cp/typeck.o: cp/typeck.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) $(EXPR_H) toplev.h \
diagnostic.h
cp/class.o: cp/class.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_H) $(TARGET_H)
cp/call.o: cp/call.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_H) $(EXPR_H) \
- $(GGC_H) diagnostic.h gt-cp-call.h
+ diagnostic.h gt-cp-call.h
cp/friend.o: cp/friend.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) toplev.h $(EXPR_H)
cp/init.o: cp/init.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) $(EXPR_H) toplev.h \
- $(GGC_H) except.h
-cp/method.o: cp/method.c $(CXX_TREE_H) $(TM_H) toplev.h $(GGC_H) $(RTL_H) $(EXPR_H) \
+ except.h
+cp/method.o: cp/method.c $(CXX_TREE_H) $(TM_H) toplev.h $(RTL_H) $(EXPR_H) \
$(TM_P_H) $(TARGET_H)
cp/cvt.o: cp/cvt.c $(CXX_TREE_H) $(TM_H) cp/decl.h flags.h toplev.h convert.h
cp/search.o: cp/search.c $(CXX_TREE_H) $(TM_H) stack.h flags.h toplev.h $(RTL_H)
-cp/tree.o: cp/tree.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(GGC_H) $(RTL_H) \
+cp/tree.o: cp/tree.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_H) \
insn-config.h integrate.h tree-inline.h real.h gt-cp-tree.h $(TARGET_H)
cp/ptree.o: cp/ptree.c $(CXX_TREE_H) $(TM_H)
cp/rtti.o: cp/rtti.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h
@@ -246,13 +247,13 @@ cp/except.o: cp/except.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) except.h toplev.
cp/expr.o: cp/expr.c $(CXX_TREE_H) $(TM_H) $(RTL_H) flags.h $(EXPR_H) toplev.h \
except.h $(TM_P_H)
cp/pt.o: cp/pt.c $(CXX_TREE_H) $(TM_H) cp/decl.h cp/lex.h \
- toplev.h $(GGC_H) $(RTL_H) except.h tree-inline.h gt-cp-pt.h
+ toplev.h $(RTL_H) except.h tree-inline.h gt-cp-pt.h
cp/error.o: cp/error.c $(CXX_TREE_H) $(TM_H) toplev.h diagnostic.h flags.h real.h \
$(LANGHOOKS_DEF_H)
-cp/repo.o: cp/repo.c $(CXX_TREE_H) $(TM_H) toplev.h $(GGC_H) diagnostic.h \
+cp/repo.o: cp/repo.c $(CXX_TREE_H) $(TM_H) toplev.h diagnostic.h \
gt-cp-repo.h
cp/semantics.o: cp/semantics.c $(CXX_TREE_H) $(TM_H) cp/lex.h except.h toplev.h \
- flags.h $(GGC_H) debug.h output.h $(RTL_H) $(TIMEVAR_H) $(EXPR_H) \
+ flags.h debug.h output.h $(RTL_H) $(TIMEVAR_H) $(EXPR_H) \
tree-inline.h
cp/dump.o: cp/dump.c $(CXX_TREE_H) $(TM_H) tree-dump.h
cp/optimize.o: cp/optimize.c $(CXX_TREE_H) $(TM_H) rtl.h integrate.h insn-config.h \
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 00458c06248..cd93f7bbe4b 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -35,7 +35,6 @@ Boston, MA 02111-1307, USA. */
#include "rtl.h"
#include "toplev.h"
#include "expr.h"
-#include "ggc.h"
#include "diagnostic.h"
extern int inhibit_warnings;
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 845ca19c738..bace3f4d7c9 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -33,7 +33,6 @@ Boston, MA 02111-1307, USA. */
#include "rtl.h"
#include "output.h"
#include "toplev.h"
-#include "ggc.h"
#include "lex.h"
#include "target.h"
@@ -125,8 +124,10 @@ static tree modify_all_vtables PARAMS ((tree, tree));
static void determine_primary_base PARAMS ((tree));
static void finish_struct_methods PARAMS ((tree));
static void maybe_warn_about_overly_private_class PARAMS ((tree));
-static int field_decl_cmp PARAMS ((const tree *, const tree *));
-static int method_name_cmp PARAMS ((const tree *, const tree *));
+static int field_decl_cmp PARAMS ((const void *, const void *));
+static int resort_field_decl_cmp PARAMS ((const void *, const void *));
+static int method_name_cmp PARAMS ((const void *, const void *));
+static int resort_method_name_cmp PARAMS ((const void *, const void *));
static void add_implicitly_declared_members PARAMS ((tree, int, int, int));
static tree fixed_type_or_null PARAMS ((tree, int *, int *));
static tree resolve_address_of_overloaded_function PARAMS ((tree, tree, int,
@@ -1449,7 +1450,8 @@ mark_primary_virtual_base (base_binfo, type)
base, then BINFO has no primary base in this graph. Called from
mark_primary_bases. DATA is the most derived type. */
-static tree dfs_unshared_virtual_bases (binfo, data)
+static tree
+dfs_unshared_virtual_bases (binfo, data)
tree binfo;
void *data;
{
@@ -1923,9 +1925,11 @@ maybe_warn_about_overly_private_class (t)
/* Function to help qsort sort FIELD_DECLs by name order. */
static int
-field_decl_cmp (x, y)
- const tree *x, *y;
+field_decl_cmp (x_p, y_p)
+ const void *x_p, *y_p;
{
+ const tree *const x = x_p;
+ const tree *const y = y_p;
if (DECL_NAME (*x) == DECL_NAME (*y))
/* A nontype is "greater" than a type. */
return DECL_DECLARES_TYPE_P (*y) - DECL_DECLARES_TYPE_P (*x);
@@ -1938,12 +1942,64 @@ field_decl_cmp (x, y)
return 1;
}
+static struct {
+ gt_pointer_operator new_value;
+ void *cookie;
+} resort_data;
+
+/* This routine compares two fields like field_decl_cmp but using the
+ pointer operator in resort_data. */
+
+static int
+resort_field_decl_cmp (x_p, y_p)
+ const void *x_p, *y_p;
+{
+ const tree *const x = x_p;
+ const tree *const y = y_p;
+
+ if (DECL_NAME (*x) == DECL_NAME (*y))
+ /* A nontype is "greater" than a type. */
+ return DECL_DECLARES_TYPE_P (*y) - DECL_DECLARES_TYPE_P (*x);
+ if (DECL_NAME (*x) == NULL_TREE)
+ return -1;
+ if (DECL_NAME (*y) == NULL_TREE)
+ return 1;
+ {
+ tree d1 = DECL_NAME (*x);
+ tree d2 = DECL_NAME (*y);
+ resort_data.new_value (&d1, resort_data.cookie);
+ resort_data.new_value (&d2, resort_data.cookie);
+ if (d1 < d2)
+ return -1;
+ }
+ return 1;
+}
+
+/* Resort DECL_SORTED_FIELDS because pointers have been reordered. */
+
+void
+resort_sorted_fields (obj, orig_obj, new_value, cookie)
+ void *obj;
+ void *orig_obj;
+ gt_pointer_operator new_value;
+ void *cookie;
+{
+ tree sf = obj;
+ resort_data.new_value = new_value;
+ resort_data.cookie = cookie;
+ qsort (&TREE_VEC_ELT (sf, 0), TREE_VEC_LENGTH (sf), sizeof (tree),
+ resort_field_decl_cmp);
+}
+
/* Comparison function to compare two TYPE_METHOD_VEC entries by name. */
static int
-method_name_cmp (m1, m2)
- const tree *m1, *m2;
+method_name_cmp (m1_p, m2_p)
+ const void *m1_p, *m2_p;
{
+ const tree *const m1 = m1_p;
+ const tree *const m2 = m2_p;
+
if (*m1 == NULL_TREE && *m2 == NULL_TREE)
return 0;
if (*m1 == NULL_TREE)
@@ -1955,6 +2011,63 @@ method_name_cmp (m1, m2)
return 1;
}
+/* This routine compares two fields like method_name_cmp but using the
+ pointer operator in resort_field_decl_data. */
+
+static int
+resort_method_name_cmp (m1_p, m2_p)
+ const void *m1_p, *m2_p;
+{
+ const tree *const m1 = m1_p;
+ const tree *const m2 = m2_p;
+ if (*m1 == NULL_TREE && *m2 == NULL_TREE)
+ return 0;
+ if (*m1 == NULL_TREE)
+ return -1;
+ if (*m2 == NULL_TREE)
+ return 1;
+ {
+ tree d1 = DECL_NAME (OVL_CURRENT (*m1));
+ tree d2 = DECL_NAME (OVL_CURRENT (*m2));
+ resort_data.new_value (&d1, resort_data.cookie);
+ resort_data.new_value (&d2, resort_data.cookie);
+ if (d1 < d2)
+ return -1;
+ }
+ return 1;
+}
+
+/* Resort TYPE_METHOD_VEC because pointers have been reordered. */
+
+void
+resort_type_method_vec (obj, orig_obj, new_value, cookie)
+ void *obj;
+ void *orig_obj;
+ gt_pointer_operator new_value;
+ void *cookie;
+{
+ tree method_vec = obj;
+ int len = TREE_VEC_LENGTH (method_vec);
+ int slot;
+
+ /* The type conversion ops have to live at the front of the vec, so we
+ can't sort them. */
+ for (slot = 2; slot < len; ++slot)
+ {
+ tree fn = TREE_VEC_ELT (method_vec, slot);
+
+ if (!DECL_CONV_FN_P (OVL_CURRENT (fn)))
+ break;
+ }
+ if (len - slot > 1)
+ {
+ resort_data.new_value = new_value;
+ resort_data.cookie = cookie;
+ qsort (&TREE_VEC_ELT (method_vec, slot), len - slot, sizeof (tree),
+ resort_method_name_cmp);
+ }
+}
+
/* Warn about duplicate methods in fn_fields. Also compact method
lists so that lookup can be made faster.
@@ -2025,7 +2138,7 @@ finish_struct_methods (t)
}
if (len - slot > 1)
qsort (&TREE_VEC_ELT (method_vec, slot), len-slot, sizeof (tree),
- (int (*)(const void *, const void *))method_name_cmp);
+ method_name_cmp);
}
/* Emit error when a duplicate definition of a type is seen. Patch up. */
@@ -5418,7 +5531,7 @@ finish_struct_1 (t)
tree field_vec = make_tree_vec (n_fields);
add_fields_to_vec (TYPE_FIELDS (t), field_vec, 0);
qsort (&TREE_VEC_ELT (field_vec, 0), n_fields, sizeof (tree),
- (int (*)(const void *, const void *))field_decl_cmp);
+ field_decl_cmp);
if (! DECL_LANG_SPECIFIC (TYPE_MAIN_DECL (t)))
retrofit_lang_decl (TYPE_MAIN_DECL (t));
DECL_SORTED_FIELDS (TYPE_MAIN_DECL (t)) = field_vec;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 8f77d10bab7..aad82c019b2 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1,5 +1,5 @@
/* Definitions for C++ parsing and type checking.
- Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2003,
2000, 2001, 2002 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
@@ -23,6 +23,7 @@ Boston, MA 02111-1307, USA. */
#ifndef GCC_CP_TREE_H
#define GCC_CP_TREE_H
+#include "ggc.h"
#include "function.h"
#include "hashtab.h"
#include "splay-tree.h"
@@ -1182,7 +1183,7 @@ struct lang_type_class GTY(())
tree as_base;
tree pure_virtuals;
tree friend_classes;
- tree methods;
+ tree GTY ((reorder ("resort_type_method_vec"))) methods;
tree key_method;
tree decl_list;
tree template_info;
@@ -1782,7 +1783,7 @@ struct lang_decl_flags GTY(())
tree GTY ((tag ("0"))) access;
/* For VAR_DECL in function, this is DECL_DISCRIMINATOR. */
- int discriminator;
+ int GTY ((tag ("1"))) discriminator;
/* In a FUNCTION_DECL for which DECL_THUNK_P holds, this is
THUNK_VIRTUAL_OFFSET. */
@@ -1790,6 +1791,9 @@ struct lang_decl_flags GTY(())
} GTY ((desc ("%1.u2sel"))) u2;
};
+/* sorted_fields is sorted based on a pointer, so we need to be able
+ to resort it if pointers get rearranged. */
+
struct lang_decl GTY(())
{
struct lang_decl_flags decl_flags;
@@ -1827,7 +1831,8 @@ struct lang_decl GTY(())
union lang_decl_u3
{
- tree GTY ((tag ("0"))) sorted_fields;
+ tree GTY ((tag ("0"), reorder ("resort_sorted_fields")))
+ sorted_fields;
struct cp_token_cache * GTY ((tag ("2"))) pending_inline_info;
struct language_function * GTY ((tag ("1")))
saved_language_function;
@@ -3555,7 +3560,7 @@ extern void init_reswords PARAMS ((void));
opname_tab[(int) MINUS_EXPR] == "-". */
extern const char **opname_tab, **assignop_tab;
-typedef struct operator_name_info_t
+typedef struct operator_name_info_t GTY(())
{
/* The IDENTIFIER_NODE for the operator. */
tree identifier;
@@ -3568,9 +3573,11 @@ typedef struct operator_name_info_t
} operator_name_info_t;
/* A mapping from tree codes to operator name information. */
-extern operator_name_info_t operator_name_info[];
+extern GTY(()) operator_name_info_t operator_name_info
+ [(int) LAST_CPLUS_TREE_CODE];
/* Similar, but for assignment operators. */
-extern operator_name_info_t assignment_operator_name_info[];
+extern GTY(()) operator_name_info_t assignment_operator_name_info
+ [(int) LAST_CPLUS_TREE_CODE];
/* in call.c */
extern bool check_dtor_name (tree, tree);
@@ -3611,10 +3618,14 @@ extern tree in_charge_arg_for_name (tree);
/* in class.c */
extern tree build_base_path PARAMS ((enum tree_code, tree, tree, int));
-extern tree convert_to_base (tree, tree, bool);
+extern tree convert_to_base PARAMS ((tree, tree, bool));
extern tree build_vtbl_ref PARAMS ((tree, tree));
extern tree build_vfn_ref PARAMS ((tree, tree));
extern tree get_vtable_decl PARAMS ((tree, int));
+extern void resort_sorted_fields
+ PARAMS ((void *, void *, gt_pointer_operator, void *));
+extern void resort_type_method_vec
+ PARAMS ((void *, void *, gt_pointer_operator, void *));
extern void add_method PARAMS ((tree, tree, int));
extern int currently_open_class PARAMS ((tree));
extern tree currently_open_derived_class PARAMS ((tree));
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 35a14e8cbe0..29a7a7fb93b 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -44,7 +44,6 @@ Boston, MA 02111-1307, USA. */
#include "except.h"
#include "toplev.h"
#include "hashtab.h"
-#include "ggc.h"
#include "tm_p.h"
#include "target.h"
#include "c-common.h"
@@ -2731,7 +2730,7 @@ pushtag (tree name, tree type, int globalize)
/* Counter used to create anonymous type names. */
-static int anon_cnt = 0;
+static GTY(()) int anon_cnt;
/* Return an IDENTIFIER which can be used as a name for
anonymous structs and unions. */
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 6363007b4ef..2491c8a3979 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -42,7 +42,6 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
#include "except.h"
#include "toplev.h"
-#include "ggc.h"
#include "timevar.h"
#include "cpplib.h"
#include "target.h"
@@ -2589,6 +2588,9 @@ finish_file ()
if (! global_bindings_p () || current_class_type || decl_namespace_list)
return;
+ if (pch_file)
+ c_common_write_pch ();
+
/* Otherwise, GDB can get confused, because in only knows
about source for LINENO-1 lines. */
lineno -= 1;
diff --git a/gcc/cp/g++spec.c b/gcc/cp/g++spec.c
index 8c1e3ae98f1..75a1d7c28a4 100644
--- a/gcc/cp/g++spec.c
+++ b/gcc/cp/g++spec.c
@@ -60,14 +60,16 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
/* If nonzero, the user gave us the `-v' flag. */
int saw_verbose_flag = 0;
- /* This will be 0 if we encounter a situation where we should not
- link in libstdc++. */
- int library = 1;
+ /* This is a tristate:
+ -1 means we should not link in libstdc++
+ 0 means we should link in libstdc++ if it is needed
+ 1 means libstdc++ is needed and should be linked in. */
+ int library = 0;
/* The number of arguments being added to what's in argv, other than
libraries. We use this to track the number of times we've inserted
-xc++/-xnone. */
- int added = 2;
+ int added = 0;
/* Used to track options that take arguments, so we don't go wrapping
those with -xc++/-xnone. */
@@ -131,10 +133,10 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
if (argv[i][0] == '-')
{
- if (library != 0 && (strcmp (argv[i], "-nostdlib") == 0
- || strcmp (argv[i], "-nodefaultlibs") == 0))
+ if (strcmp (argv[i], "-nostdlib") == 0
+ || strcmp (argv[i], "-nodefaultlibs") == 0)
{
- library = 0;
+ library = -1;
}
else if (strcmp (argv[i], "-lm") == 0
|| strcmp (argv[i], "-lmath") == 0
@@ -152,31 +154,37 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
else if (strcmp (argv[i], "-pg") == 0 || strcmp (argv[i], "-p") == 0)
saw_profile_flag++;
else if (strcmp (argv[i], "-v") == 0)
+ saw_verbose_flag = 1;
+ else if (strncmp (argv[i], "-x", 2) == 0)
{
- saw_verbose_flag = 1;
- if (argc == 2)
+ if (library == 0)
{
- /* If they only gave us `-v', don't try to link
- in libg++. */
- library = 0;
+ const char * arg;
+ if (argv[i][2] != '\0')
+ arg = argv[i]+2;
+ else if (argv[i+1] != NULL)
+ arg = argv[i+1];
+ else /* Error condition, message will be printed later. */
+ arg = "";
+ if (strcmp (arg, "c++") == 0
+ || strcmp (arg, "c++-cpp-output") == 0)
+ library = 1;
}
+ saw_speclang = 1;
}
- else if (strncmp (argv[i], "-x", 2) == 0)
- saw_speclang = 1;
else if (((argv[i][2] == '\0'
&& (char *)strchr ("bBVDUoeTuIYmLiA", argv[i][1]) != NULL)
|| strcmp (argv[i], "-Xlinker") == 0
|| strcmp (argv[i], "-Tdata") == 0))
quote = argv[i];
- else if (library != 0 && ((argv[i][2] == '\0'
- && (char *) strchr ("cSEM", argv[i][1]) != NULL)
- || strcmp (argv[i], "-MM") == 0
- || strcmp (argv[i], "-fsyntax-only") == 0))
+ else if ((argv[i][2] == '\0'
+ && (char *) strchr ("cSEM", argv[i][1]) != NULL)
+ || strcmp (argv[i], "-MM") == 0
+ || strcmp (argv[i], "-fsyntax-only") == 0)
{
/* Don't specify libraries if we won't link, since that would
cause a warning. */
- library = 0;
- added -= 2;
+ library = -1;
}
else if (strcmp (argv[i], "-static-libgcc") == 0
|| strcmp (argv[i], "-static") == 0)
@@ -195,16 +203,28 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
continue;
}
- /* If the filename ends in .c or .i, put options around it.
+ /* If the filename ends in .[chi], put options around it.
But not if a specified -x option is currently active. */
len = strlen (argv[i]);
if (len > 2
- && (argv[i][len - 1] == 'c' || argv[i][len - 1] == 'i')
+ && (argv[i][len - 1] == 'c'
+ || argv[i][len - 1] == 'i'
+ || argv[i][len - 1] == 'h')
&& argv[i][len - 2] == '.')
{
args[i] |= LANGSPEC;
added += 2;
}
+
+ /* If we don't know that this is a header file, we might
+ need to be linking in the libraries. */
+ if (library == 0)
+ {
+ if ((len <= 2 || strcmp (argv[i] + (len - 2), ".H") != 0)
+ && (len <= 2 || strcmp (argv[i] + (len - 2), ".h") != 0)
+ && (len <= 3 || strcmp (argv[i] + (len - 3), ".hh") != 0))
+ library = 1;
+ }
}
}
@@ -212,7 +232,7 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
fatal ("argument to `%s' missing\n", quote);
/* If we know we don't have to do anything, bail now. */
- if (! added && ! library)
+ if (! added && library <= 0)
{
free (args);
return;
@@ -225,7 +245,7 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
#endif
/* Make sure to have room for the trailing NULL argument. */
- num_args = argc + added + need_math + shared_libgcc + 1;
+ num_args = argc + added + need_math + shared_libgcc + (library > 0) + 1;
arglist = (const char **) xmalloc (num_args * sizeof (char *));
i = 0;
@@ -241,27 +261,37 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
/* Make sure -lstdc++ is before the math library, since libstdc++
itself uses those math routines. */
- if (!saw_math && (args[i] & MATHLIB) && library)
+ if (!saw_math && (args[i] & MATHLIB) && library > 0)
{
--j;
saw_math = argv[i];
}
- if (!saw_libc && (args[i] & WITHLIBC) && library)
+ if (!saw_libc && (args[i] & WITHLIBC) && library > 0)
{
--j;
saw_libc = argv[i];
}
- /* Wrap foo.c and foo.i files in a language specification to
+ /* Wrap foo.[chi] files in a language specification to
force the gcc compiler driver to run cc1plus on them. */
if (args[i] & LANGSPEC)
{
int len = strlen (argv[i]);
- if (argv[i][len - 1] == 'i')
- arglist[j++] = "-xc++-cpp-output";
- else
- arglist[j++] = "-xc++";
+ switch (argv[i][len - 1])
+ {
+ case 'c':
+ arglist[j++] = "-xc++";
+ break;
+ case 'i':
+ arglist[j++] = "-xc++-cpp-output";
+ break;
+ case 'h':
+ arglist[j++] = "-xc++-header";
+ break;
+ default:
+ abort ();
+ }
arglist[j++] = argv[i];
arglist[j] = "-xnone";
}
@@ -271,7 +301,7 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
}
/* Add `-lstdc++' if we haven't already done so. */
- if (library)
+ if (library > 0)
{
arglist[j++] = saw_profile_flag ? LIBSTDCXX_PROFILE : LIBSTDCXX;
added_libraries++;
@@ -285,7 +315,7 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
}
if (saw_math)
arglist[j++] = saw_math;
- else if (library && need_math)
+ else if (library > 0 && need_math)
{
arglist[j++] = saw_profile_flag ? MATH_LIBRARY_PROFILE : MATH_LIBRARY;
added_libraries++;
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 2fd0c50779b..964ee1e0c12 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -34,7 +34,6 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
#include "except.h"
#include "toplev.h"
-#include "ggc.h"
static void construct_virtual_base (tree, tree);
static void expand_aggr_init_1 PARAMS ((tree, tree, tree, tree, int));
diff --git a/gcc/cp/lang-specs.h b/gcc/cp/lang-specs.h
index e8264676449..cf4ca4cee36 100644
--- a/gcc/cp/lang-specs.h
+++ b/gcc/cp/lang-specs.h
@@ -33,6 +33,19 @@ Boston, MA 02111-1307, USA. */
{".c++", "@c++", 0},
{".C", "@c++", 0},
{".CPP", "@c++", 0},
+ {".H", "@c++-header", 0},
+ {".hh", "@c++-header", 0},
+ {"@c++-header",
+ "%{E|M|MM:cc1plus -E %{!no-gcc:-D__GNUG__=%v1}\
+ %(cpp_options) %2 %(cpp_debug_options)}\
+ %{!E:%{!M:%{!MM:\
+ %{save-temps:cc1plus -E %{!no-gcc:-D__GNUG__=%v1}\
+ %(cpp_options) %2 %b.ii \n}\
+ cc1plus %{save-temps:-fpreprocessed %b.ii}\
+ %{!save-temps:%(cpp_unique_options) %{!no-gcc:-D__GNUG__=%v1}}\
+ %(cc1_options) %2 %{+e1*}\
+ -o %g.s %{!o*:--output-pch=%i.pch} %W{o*:--output-pch=%*}%V}}}",
+ CPLUSPLUS_CPP_SPEC},
{"@c++",
"%{E|M|MM:cc1plus -E %{!no-gcc:-D__GNUG__=%v1}\
%(cpp_options) %2 %(cpp_debug_options)}\
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index 29753992b54..5749fc463b7 100644
--- a/gcc/cp/lex.c
+++ b/gcc/cp/lex.c
@@ -36,7 +36,6 @@ Boston, MA 02111-1307, USA. */
#include "c-pragma.h"
#include "toplev.h"
#include "output.h"
-#include "ggc.h"
#include "tm_p.h"
#include "timevar.h"
#include "diagnostic.h"
@@ -380,10 +379,7 @@ init_reswords ()
int mask = ((flag_no_asm ? D_ASM : 0)
| (flag_no_gnu_keywords ? D_EXT : 0));
- /* It is not necessary to register ridpointers as a GC root, because
- all the trees it points to are permanently interned in the
- get_identifier hash anyway. */
- ridpointers = (tree *) xcalloc ((int) RID_MAX, sizeof (tree));
+ ridpointers = (tree *) ggc_calloc ((int) RID_MAX, sizeof (tree));
for (i = 0; i < ARRAY_SIZE (reswords); i++)
{
id = get_identifier (reswords[i].word);
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index f4960b29c53..883a81f73fd 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -1,7 +1,7 @@
/* Handle the hair of processing (but not expanding) inline functions.
Also manage function and variable name overloading.
- Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+ 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC.
@@ -34,7 +34,6 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
#include "flags.h"
#include "toplev.h"
-#include "ggc.h"
#include "tm_p.h"
#include "target.h"
diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c
index fe924f4aae4..8f08c9ac22b 100644
--- a/gcc/cp/optimize.c
+++ b/gcc/cp/optimize.c
@@ -31,7 +31,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "integrate.h"
#include "toplev.h"
#include "varray.h"
-#include "ggc.h"
#include "params.h"
#include "hashtab.h"
#include "debug.h"
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index e88045dc117..629ba5d8178 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -32,7 +32,6 @@
#include "decl.h"
#include "flags.h"
#include "diagnostic.h"
-#include "ggc.h"
#include "toplev.h"
#include "output.h"
@@ -213,8 +212,8 @@ typedef struct cp_lexer GTY (())
/* Prototypes. */
-static cp_lexer *cp_lexer_new
- PARAMS ((bool));
+static cp_lexer *cp_lexer_new_main
+ PARAMS ((void));
static cp_lexer *cp_lexer_new_from_tokens
PARAMS ((struct cp_token_cache *));
static int cp_lexer_saving_tokens
@@ -292,29 +291,37 @@ static void cp_lexer_stop_debugging
/* The stream to which debugging output should be written. */
static FILE *cp_lexer_debug_stream;
-/* Create a new C++ lexer. If MAIN_LEXER_P is true the new lexer is
- the main lexer -- i.e, the lexer that gets tokens from the
- preprocessor. Otherwise, it is a lexer that uses a cache of stored
- tokens. */
+/* Create a new main C++ lexer, the lexer that gets tokens from the
+ preprocessor. */
static cp_lexer *
-cp_lexer_new (bool main_lexer_p)
+cp_lexer_new_main (void)
{
cp_lexer *lexer;
+ cp_token first_token;
+
+ /* It's possible that lexing the first token will load a PCH file,
+ which is a GC collection point. So we have to grab the first
+ token before allocating any memory. */
+ cp_lexer_get_preprocessor_token (NULL, &first_token);
+ cpp_get_callbacks (parse_in)->valid_pch = NULL;
/* Allocate the memory. */
lexer = (cp_lexer *) ggc_alloc_cleared (sizeof (cp_lexer));
/* Create the circular buffer. */
lexer->buffer = ((cp_token *)
- ggc_alloc (CP_TOKEN_BUFFER_SIZE * sizeof (cp_token)));
+ ggc_calloc (CP_TOKEN_BUFFER_SIZE, sizeof (cp_token)));
lexer->buffer_end = lexer->buffer + CP_TOKEN_BUFFER_SIZE;
- /* There are no tokens in the buffer. */
- lexer->last_token = lexer->buffer;
+ /* There is one token in the buffer. */
+ lexer->last_token = lexer->buffer + 1;
+ lexer->first_token = lexer->buffer;
+ lexer->next_token = lexer->buffer;
+ memcpy (lexer->buffer, &first_token, sizeof (cp_token));
/* This lexer obtains more tokens by calling c_lex. */
- lexer->main_lexer_p = main_lexer_p;
+ lexer->main_lexer_p = true;
/* Create the SAVED_TOKENS stack. */
VARRAY_INT_INIT (lexer->saved_tokens, CP_SAVED_TOKENS_SIZE, "saved_tokens");
@@ -339,15 +346,14 @@ cp_lexer_new_from_tokens (cp_token_cache *tokens)
cp_token_block *block;
ptrdiff_t num_tokens;
- /* Create the lexer. */
- lexer = cp_lexer_new (/*main_lexer_p=*/false);
+ /* Allocate the memory. */
+ lexer = (cp_lexer *) ggc_alloc_cleared (sizeof (cp_lexer));
/* Create a new buffer, appropriately sized. */
num_tokens = 0;
for (block = tokens->first; block != NULL; block = block->next)
num_tokens += block->num_tokens;
- lexer->buffer = ((cp_token *)
- ggc_alloc (num_tokens * sizeof (cp_token)));
+ lexer->buffer = ((cp_token *) ggc_alloc (num_tokens * sizeof (cp_token)));
lexer->buffer_end = lexer->buffer + num_tokens;
/* Install the tokens. */
@@ -365,6 +371,18 @@ cp_lexer_new_from_tokens (cp_token_cache *tokens)
/* The buffer is full. */
lexer->last_token = lexer->first_token;
+ /* This lexer doesn't obtain more tokens. */
+ lexer->main_lexer_p = false;
+
+ /* Create the SAVED_TOKENS stack. */
+ VARRAY_INT_INIT (lexer->saved_tokens, CP_SAVED_TOKENS_SIZE, "saved_tokens");
+
+ /* Create the STRINGS array. */
+ VARRAY_TREE_INIT (lexer->string_tokens, 32, "strings");
+
+ /* Assume we are not debugging. */
+ lexer->debugging_p = false;
+
return lexer;
}
@@ -610,7 +628,7 @@ cp_lexer_get_preprocessor_token (lexer, token)
bool done;
/* If this not the main lexer, return a terminating CPP_EOF token. */
- if (!lexer->main_lexer_p)
+ if (lexer != NULL && !lexer->main_lexer_p)
{
token->type = CPP_EOF;
token->line_number = 0;
@@ -2472,9 +2490,14 @@ static cp_parser *
cp_parser_new ()
{
cp_parser *parser;
+ cp_lexer *lexer;
+
+ /* cp_lexer_new_main is called before calling ggc_alloc because
+ cp_lexer_new_main might load a PCH file. */
+ lexer = cp_lexer_new_main ();
parser = (cp_parser *) ggc_alloc_cleared (sizeof (cp_parser));
- parser->lexer = cp_lexer_new (/*main_lexer_p=*/true);
+ parser->lexer = lexer;
parser->context = cp_parser_context_new (NULL);
/* For now, we always accept GNU extensions. */
@@ -14422,9 +14445,7 @@ cp_parser_late_parsing_for_member (parser, member_function)
/* Set the current source position to be the location of the first
token in the saved inline body. */
- cp_lexer_set_source_position_from_token
- (parser->lexer,
- cp_lexer_peek_token (parser->lexer));
+ (void) cp_lexer_peek_token (parser->lexer);
/* Let the front end know that we going to be defining this
function. */
@@ -14477,8 +14498,7 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
/* Set the current source position to be the location of the
first token in the default argument. */
- cp_lexer_set_source_position_from_token
- (parser->lexer, cp_lexer_peek_token (parser->lexer));
+ (void) cp_lexer_peek_token (parser->lexer);
/* Local variable names (and the `this' keyword) may not appear
in a default argument. */
@@ -14996,6 +15016,8 @@ yyparse ()
the_parser = cp_parser_new ();
error_occurred = cp_parser_translation_unit (the_parser);
the_parser = NULL;
+
+ finish_file ();
return error_occurred;
}
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 7802e25b573..e7486afca25 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -41,7 +41,6 @@ Boston, MA 02111-1307, USA. */
#include "except.h"
#include "toplev.h"
#include "rtl.h"
-#include "ggc.h"
#include "timevar.h"
/* The type of functions taking a tree, and some additional data, and
diff --git a/gcc/cp/repo.c b/gcc/cp/repo.c
index 105e4df51ac..603b04eef06 100644
--- a/gcc/cp/repo.c
+++ b/gcc/cp/repo.c
@@ -35,7 +35,6 @@ Boston, MA 02111-1307, USA. */
#include "input.h"
#include "obstack.h"
#include "toplev.h"
-#include "ggc.h"
#include "diagnostic.h"
static tree repo_get_id (tree);
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 13ed4b0aa53..5e9b3955ad4 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -33,7 +33,6 @@ Boston, MA 02111-1307, USA. */
#include "flags.h"
#include "rtl.h"
#include "output.h"
-#include "ggc.h"
#include "toplev.h"
#include "stack.h"
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 0aeaa0db77e..3ed9f2e20a3 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -3,7 +3,7 @@
building RTL. These routines are used both during actual parsing
and during the instantiation of template functions.
- Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Written by Mark Mitchell (mmitchell@usa.net) based on code found
formerly in parse.y and pt.c.
@@ -35,7 +35,6 @@
#include "lex.h"
#include "toplev.h"
#include "flags.h"
-#include "ggc.h"
#include "rtl.h"
#include "expr.h"
#include "output.h"
@@ -1628,8 +1627,6 @@ finish_translation_unit ()
/* Do file scope __FUNCTION__ et al. */
finish_fname_decls ();
-
- finish_file ();
}
/* Finish a template type parameter, specified as AGGR IDENTIFIER.
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 93c62dac158..a3b6ff14a4f 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -30,7 +30,6 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "rtl.h"
#include "toplev.h"
-#include "ggc.h"
#include "insn-config.h"
#include "integrate.h"
#include "tree-inline.h"
diff --git a/gcc/cppfiles.c b/gcc/cppfiles.c
index 4d8219661d0..203619f30b8 100644
--- a/gcc/cppfiles.c
+++ b/gcc/cppfiles.c
@@ -22,6 +22,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include <dirent.h>
#include "coretypes.h"
#include "tm.h"
#include "cpplib.h"
@@ -87,6 +88,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* This structure is used for the table of all includes. */
struct include_file {
const char *name; /* actual path name of file */
+ const char *header_name; /* the original header found */
const cpp_hashnode *cmacro; /* macro, if any, preventing reinclusion. */
const struct search_path *foundhere;
/* location in search path where file was
@@ -98,6 +100,13 @@ struct include_file {
unsigned short include_count; /* number of times file has been read */
unsigned short refcnt; /* number of stacked buffers using this file */
unsigned char mapped; /* file buffer is mmapped */
+ unsigned char pch; /* 0: file not known to be a PCH.
+ 1: file is a PCH
+ (on return from find_include_file).
+ 2: file is not and never will be a valid
+ precompiled header.
+ 3: file is always a valid precompiled
+ header. */
};
/* Variable length record files on VMS will have a stat size that includes
@@ -118,6 +127,7 @@ struct include_file {
((inc)->cmacro && ((inc)->cmacro == NEVER_REREAD \
|| (inc)->cmacro->type == NT_MACRO))
#define NO_INCLUDE_PATH ((struct include_file *) -1)
+#define INCLUDE_PCH_P(F) (((F)->pch & 1) != 0)
static struct file_name_map *read_name_map
PARAMS ((cpp_reader *, const char *));
@@ -130,6 +140,11 @@ static struct include_file *
find_include_file PARAMS ((cpp_reader *, const cpp_token *,
enum include_type));
static struct include_file *open_file PARAMS ((cpp_reader *, const char *));
+static struct include_file *validate_pch PARAMS ((cpp_reader *,
+ const char *,
+ const char *));
+static struct include_file *open_file_pch PARAMS ((cpp_reader *,
+ const char *));
static int read_include_file PARAMS ((cpp_reader *, struct include_file *));
static bool stack_include_file PARAMS ((cpp_reader *, struct include_file *));
static void purge_cache PARAMS ((struct include_file *));
@@ -212,6 +227,7 @@ find_or_create_entry (pfile, fname)
{
file = xcnew (struct include_file);
file->name = name;
+ file->header_name = name;
file->err_no = errno;
node = splay_tree_insert (pfile->all_include_files,
(splay_tree_key) file->name,
@@ -306,6 +322,89 @@ open_file (pfile, filename)
return 0;
}
+static struct include_file *
+validate_pch (pfile, filename, pchname)
+ cpp_reader *pfile;
+ const char *filename;
+ const char *pchname;
+{
+ struct include_file * file;
+
+ file = open_file (pfile, pchname);
+ if (file == NULL)
+ return NULL;
+ if ((file->pch & 2) == 0)
+ file->pch = pfile->cb.valid_pch (pfile, pchname, file->fd);
+ if (INCLUDE_PCH_P (file))
+ {
+ file->header_name = _cpp_simplify_pathname (xstrdup (filename));
+ return file;
+ }
+ close (file->fd);
+ file->fd = -1;
+ return NULL;
+}
+
+
+/* Like open_file, but also look for a precompiled header if (a) one exists
+ and (b) it is valid. */
+static struct include_file *
+open_file_pch (pfile, filename)
+ cpp_reader *pfile;
+ const char *filename;
+{
+ if (filename[0] != '\0'
+ && pfile->cb.valid_pch != NULL)
+ {
+ size_t namelen = strlen (filename);
+ char *pchname = alloca (namelen + 5);
+ struct include_file * file;
+ splay_tree_node nd;
+
+ memcpy (pchname, filename, namelen);
+ memcpy (pchname + namelen, ".pch", 5);
+
+ nd = find_or_create_entry (pfile, pchname);
+ file = (struct include_file *) nd->value;
+
+ if (file != NULL)
+ {
+ if (stat (file->name, &file->st) == 0 && S_ISDIR (file->st.st_mode))
+ {
+ DIR * thedir;
+ struct dirent *d;
+ size_t subname_len = namelen + 64;
+ char *subname = xmalloc (subname_len);
+
+ thedir = opendir (pchname);
+ if (thedir == NULL)
+ return NULL;
+ memcpy (subname, pchname, namelen + 4);
+ subname[namelen+4] = '/';
+ while ((d = readdir (thedir)) != NULL)
+ {
+ if (strlen (d->d_name) + namelen + 7 > subname_len)
+ {
+ subname_len = strlen (d->d_name) + namelen + 64;
+ subname = xrealloc (subname, subname_len);
+ }
+ strcpy (subname + namelen + 5, d->d_name);
+ file = validate_pch (pfile, filename, subname);
+ if (file)
+ break;
+ }
+ closedir (thedir);
+ free (subname);
+ }
+ else
+ file = validate_pch (pfile, filename, pchname);
+ if (file)
+ return file;
+ }
+ }
+ return open_file (pfile, filename);
+}
+
/* Place the file referenced by INC into a new buffer on the buffer
stack, unless there are errors, or the file is not re-included
because of e.g. multiple-include guards. Returns true if a buffer
@@ -332,6 +431,15 @@ stack_include_file (pfile, inc)
deps_add_dep (pfile->deps, inc->name);
}
+ /* PCH files get dealt with immediately. */
+ if (INCLUDE_PCH_P (inc))
+ {
+ pfile->cb.read_pch (pfile, inc->name, inc->fd, inc->header_name);
+ close (inc->fd);
+ inc->fd = -1;
+ return false;
+ }
+
/* Not in cache? */
if (! inc->buffer)
{
@@ -579,7 +687,7 @@ find_include_file (pfile, header, type)
char *name, *n;
if (IS_ABSOLUTE_PATHNAME (fname))
- return open_file (pfile, fname);
+ return open_file_pch (pfile, fname);
/* For #include_next, skip in the search path past the dir in which
the current file was found, but if it was found via an absolute
@@ -615,7 +723,7 @@ find_include_file (pfile, header, type)
else
n = name;
- file = open_file (pfile, n);
+ file = open_file_pch (pfile, n);
if (file)
{
file->foundhere = path;
@@ -757,6 +865,9 @@ _cpp_read_file (pfile, fname)
cpp_reader *pfile;
const char *fname;
{
+ /* This uses open_file, because we don't allow a PCH to be used as
+ the toplevel compilation (that would prevent re-compiling an
+ existing PCH without deleting it first). */
struct include_file *f = open_file (pfile, fname);
if (f == NULL)
diff --git a/gcc/cpphash.h b/gcc/cpphash.h
index 16e8dfe08fe..d5a0b5d155a 100644
--- a/gcc/cpphash.h
+++ b/gcc/cpphash.h
@@ -449,6 +449,10 @@ struct cpp_reader
/* Used to save the original line number during traditional
preprocessing. */
unsigned int saved_line;
+
+ /* A saved list of the defined macros, for dependency checking
+ of precompiled headers. */
+ struct cpp_savedstate *savedstate;
};
/* Character classes. Based on the more primitive macros in safe-ctype.h.
@@ -542,6 +546,8 @@ extern void _cpp_maybe_push_include_file PARAMS ((cpp_reader *));
extern int _cpp_test_assertion PARAMS ((cpp_reader *, unsigned int *));
extern int _cpp_handle_directive PARAMS ((cpp_reader *, int));
extern void _cpp_define_builtin PARAMS ((cpp_reader *, const char *));
+extern char ** _cpp_save_pragma_names PARAMS ((cpp_reader *));
+extern void _cpp_restore_pragma_names PARAMS ((cpp_reader *, char **));
extern void _cpp_do__Pragma PARAMS ((cpp_reader *));
extern void _cpp_init_directives PARAMS ((cpp_reader *));
extern void _cpp_init_internal_pragmas PARAMS ((cpp_reader *));
diff --git a/gcc/cpplib.c b/gcc/cpplib.c
index e032e75bef5..1019a2a9713 100644
--- a/gcc/cpplib.c
+++ b/gcc/cpplib.c
@@ -121,6 +121,11 @@ static struct pragma_entry *lookup_pragma_entry
static struct pragma_entry *insert_pragma_entry
PARAMS ((cpp_reader *, struct pragma_entry **, const cpp_hashnode *,
pragma_cb));
+static int count_registered_pragmas PARAMS ((struct pragma_entry *));
+static char ** save_registered_pragmas
+ PARAMS ((struct pragma_entry *, char **));
+static char ** restore_registered_pragmas
+ PARAMS ((cpp_reader *, struct pragma_entry *, char **));
static void do_pragma_once PARAMS ((cpp_reader *));
static void do_pragma_poison PARAMS ((cpp_reader *));
static void do_pragma_system_header PARAMS ((cpp_reader *));
@@ -1085,6 +1090,85 @@ _cpp_init_internal_pragmas (pfile)
cpp_register_pragma (pfile, "GCC", "dependency", do_pragma_dependency);
}
+/* Return the number of registered pragmas in PE. */
+
+static int
+count_registered_pragmas (pe)
+ struct pragma_entry *pe;
+{
+ int ct = 0;
+ for (; pe != NULL; pe = pe->next)
+ {
+ if (pe->is_nspace)
+ ct += count_registered_pragmas (pe->u.space);
+ ct++;
+ }
+ return ct;
+}
+
+/* Save into SD the names of the registered pragmas referenced by PE,
+ and return a pointer to the next free space in SD. */
+
+static char **
+save_registered_pragmas (pe, sd)
+ struct pragma_entry *pe;
+ char **sd;
+{
+ for (; pe != NULL; pe = pe->next)
+ {
+ if (pe->is_nspace)
+ sd = save_registered_pragmas (pe->u.space, sd);
+ *sd++ = xmemdup (HT_STR (&pe->pragma->ident),
+ HT_LEN (&pe->pragma->ident),
+ HT_LEN (&pe->pragma->ident) + 1);
+ }
+ return sd;
+}
+
+/* Return a newly-allocated array which saves the names of the
+ registered pragmas. */
+
+char **
+_cpp_save_pragma_names (pfile)
+ cpp_reader *pfile;
+{
+ int ct = count_registered_pragmas (pfile->pragmas);
+ char **result = xnewvec (char *, ct);
+ (void) save_registered_pragmas (pfile->pragmas, result);
+ return result;
+}
+
+/* Restore from SD the names of the registered pragmas referenced by PE,
+ and return a pointer to the next unused name in SD. */
+
+static char **
+restore_registered_pragmas (pfile, pe, sd)
+ cpp_reader *pfile;
+ struct pragma_entry *pe;
+ char **sd;
+{
+ for (; pe != NULL; pe = pe->next)
+ {
+ if (pe->is_nspace)
+ sd = restore_registered_pragmas (pfile, pe->u.space, sd);
+ pe->pragma = cpp_lookup (pfile, U *sd, strlen (*sd));
+ free (*sd);
+ sd++;
+ }
+ return sd;
+}
+
+/* Restore the names of the registered pragmas from SAVED. */
+
+void
+_cpp_restore_pragma_names (pfile, saved)
+ cpp_reader *pfile;
+ char **saved;
+{
+ (void) restore_registered_pragmas (pfile, pfile->pragmas, saved);
+ free (saved);
+}
+
/* Pragmata handling. We handle some, and pass the rest on to the
front end. C99 defines three pragmas and says that no macro
expansion is to be performed on them; whether or not macro
diff --git a/gcc/cpplib.h b/gcc/cpplib.h
index 271a75531e9..bccfecf86be 100644
--- a/gcc/cpplib.h
+++ b/gcc/cpplib.h
@@ -400,6 +400,12 @@ struct cpp_options
/* Nonzero means __STDC__ should have the value 0 in system headers. */
unsigned char stdc_0_in_system_headers;
+
+ /* True to warn about precompiled header files we couldn't use. */
+ bool warn_invalid_pch;
+
+ /* True if dependencies should be restored from a precompiled header. */
+ bool restore_pch_deps;
};
/* Call backs. */
@@ -417,6 +423,8 @@ struct cpp_callbacks
/* Called when the client has a chance to properly register
built-ins with cpp_define() and cpp_assert(). */
void (*register_builtins) PARAMS ((cpp_reader *));
+ int (*valid_pch) PARAMS ((cpp_reader *, const char *, int));
+ void (*read_pch) PARAMS ((cpp_reader *, const char *, int, const char *));
};
/* Name under which this program was invoked. */
@@ -472,7 +480,7 @@ enum builtin_type
/* The common part of an identifier node shared amongst all 3 C front
ends. Also used to store CPP identifiers, which are a superset of
identifiers in the grammatical sense. */
-struct cpp_hashnode
+struct cpp_hashnode GTY(())
{
struct ht_identifier ident;
unsigned int is_directive : 1;
@@ -485,11 +493,15 @@ struct cpp_hashnode
union _cpp_hashnode_value
{
- cpp_macro *macro; /* If a macro. */
- struct answer *answers; /* Answers to an assertion. */
- enum builtin_type builtin; /* Code for a builtin macro. */
- unsigned short arg_index; /* Macro argument index. */
- } value;
+ /* If a macro. */
+ cpp_macro * GTY((skip (""))) macro;
+ /* Answers to an assertion. */
+ struct answer * GTY ((skip (""))) answers;
+ /* Code for a builtin macro. */
+ enum builtin_type GTY ((tag ("1"))) builtin;
+ /* Macro argument index. */
+ unsigned short GTY ((tag ("0"))) arg_index;
+ } GTY ((desc ("0"))) value;
};
/* Call this first to get a handle to pass to other functions. */
@@ -722,6 +734,17 @@ extern unsigned char *cpp_quote_string PARAMS ((unsigned char *,
extern int cpp_included PARAMS ((cpp_reader *, const char *));
extern void cpp_make_system_header PARAMS ((cpp_reader *, int, int));
+/* In cpppch.c */
+struct save_macro_data;
+extern int cpp_save_state PARAMS ((cpp_reader *, FILE *));
+extern int cpp_write_pch_deps PARAMS ((cpp_reader *, FILE *));
+extern int cpp_write_pch_state PARAMS ((cpp_reader *, FILE *));
+extern int cpp_valid_state PARAMS ((cpp_reader *, const char *, int));
+extern void cpp_prepare_state PARAMS ((cpp_reader *,
+ struct save_macro_data **));
+extern int cpp_read_state PARAMS ((cpp_reader *, const char *, FILE *,
+ struct save_macro_data *));
+
/* In cppmain.c */
extern void cpp_preprocess_file PARAMS ((cpp_reader *, const char *, FILE *));
diff --git a/gcc/cpppch.c b/gcc/cpppch.c
new file mode 100644
index 00000000000..e7f0c91adfd
--- /dev/null
+++ b/gcc/cpppch.c
@@ -0,0 +1,684 @@
+/* Part of CPP library. (Precompiled header reading/writing.)
+ Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+
+This program 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.
+
+This program 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 this program; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "cpplib.h"
+#include "cpphash.h"
+#include "intl.h"
+#include "hashtab.h"
+#include "mkdeps.h"
+
+static int write_macdef PARAMS ((cpp_reader *, cpp_hashnode *, void *));
+static int save_idents PARAMS ((cpp_reader *, cpp_hashnode *, void *));
+static hashval_t hashmem PARAMS ((const void *, size_t));
+static hashval_t cpp_string_hash PARAMS ((const void *));
+static int cpp_string_eq PARAMS ((const void *, const void *));
+static int count_defs PARAMS ((cpp_reader *, cpp_hashnode *, void *));
+static int write_defs PARAMS ((cpp_reader *, cpp_hashnode *, void *));
+static int save_macros PARAMS ((cpp_reader *, cpp_hashnode *, void *));
+static int reset_ht PARAMS ((cpp_reader *, cpp_hashnode *, void *));
+
+/* This structure represents a macro definition on disk. */
+struct macrodef_struct
+{
+ unsigned int definition_length;
+ unsigned short name_length;
+ unsigned short flags;
+};
+
+/* This is how we write out a macro definition.
+ Suitable for being called by cpp_forall_identifiers. */
+
+static int
+write_macdef (pfile, hn, file_p)
+ cpp_reader *pfile;
+ cpp_hashnode *hn;
+ void *file_p;
+{
+ FILE *f = (FILE *) file_p;
+ switch (hn->type)
+ {
+ case NT_VOID:
+ if (! (hn->flags & NODE_POISONED))
+ return 1;
+
+ case NT_MACRO:
+ if ((hn->flags & NODE_BUILTIN))
+ return 1;
+
+ {
+ struct macrodef_struct s;
+ const unsigned char *defn;
+
+ s.name_length = NODE_LEN (hn);
+ s.flags = hn->flags & NODE_POISONED;
+
+ if (hn->type == NT_MACRO)
+ {
+ defn = cpp_macro_definition (pfile, hn);
+ s.definition_length = ustrlen (defn);
+ }
+ else
+ {
+ defn = NODE_NAME (hn);
+ s.definition_length = s.name_length;
+ }
+
+ if (fwrite (&s, sizeof (s), 1, f) != 1
+ || fwrite (defn, 1, s.definition_length, f) != s.definition_length)
+ {
+ cpp_errno (pfile, DL_ERROR, "while writing precompiled header");
+ return 0;
+ }
+ }
+ return 1;
+
+ case NT_ASSERTION:
+ /* Not currently implemented. */
+ return 1;
+
+ default:
+ abort ();
+ }
+}
+
+/* This structure records the names of the defined macros.
+ It's also used as a callback structure for size_initial_idents
+ and save_idents. */
+
+struct cpp_savedstate
+{
+ /* A hash table of the defined identifiers. */
+ htab_t definedhash;
+ /* The size of the definitions of those identifiers (the size of
+ 'definedstrs'). */
+ size_t hashsize;
+ /* Space for the next definition. Definitions are null-terminated
+ strings. */
+ unsigned char *definedstrs;
+};
+
+/* Save this identifier into the state: put it in the hash table,
+ put the definition in 'definedstrs'. */
+
+static int
+save_idents (pfile, hn, ss_p)
+ cpp_reader *pfile ATTRIBUTE_UNUSED;
+ cpp_hashnode *hn;
+ void *ss_p;
+{
+ struct cpp_savedstate *const ss = (struct cpp_savedstate *)ss_p;
+
+ if (hn->type != NT_VOID)
+ {
+ struct cpp_string news;
+ void **slot;
+
+ news.len = NODE_LEN (hn);
+ news.text= NODE_NAME (hn);
+ slot = htab_find_slot (ss->definedhash, &news, INSERT);
+ if (*slot == NULL)
+ {
+ struct cpp_string *sp;
+ unsigned char *text;
+
+ sp = xmalloc (sizeof (struct cpp_string));
+ *slot = sp;
+
+ sp->len = NODE_LEN (hn);
+ sp->text = text = xmalloc (NODE_LEN (hn));
+ memcpy (text, NODE_NAME (hn), NODE_LEN (hn));
+ }
+ }
+
+ return 1;
+}
+
+/* Hash some memory in a generic way. */
+
+static hashval_t
+hashmem (p_p, sz)
+ const void *p_p;
+ size_t sz;
+{
+ const unsigned char *p = (const unsigned char *)p_p;
+ size_t i;
+ hashval_t h;
+
+ h = 0;
+ for (i = 0; i < sz; i++)
+ h = h * 67 - (*p++ - 113);
+ return h;
+}
+
+/* Hash a cpp string for the hashtable machinery. */
+
+static hashval_t
+cpp_string_hash (a_p)
+ const void *a_p;
+{
+ const struct cpp_string *a = (const struct cpp_string *) a_p;
+ return hashmem (a->text, a->len);
+}
+
+/* Compare two cpp strings for the hashtable machinery. */
+
+static int
+cpp_string_eq (a_p, b_p)
+ const void *a_p;
+ const void *b_p;
+{
+ const struct cpp_string *a = (const struct cpp_string *) a_p;
+ const struct cpp_string *b = (const struct cpp_string *) b_p;
+ return (a->len == b->len
+ && memcmp (a->text, b->text, a->len) == 0);
+}
+
+/* Save the current definitions of the cpp_reader for dependency
+ checking purposes. When writing a precompiled header, this should
+ be called at the same point in the compilation as cpp_valid_state
+ would be called when reading the precompiled header back in. */
+
+int
+cpp_save_state (r, f)
+ cpp_reader *r;
+ FILE *f;
+{
+ /* Save the list of non-void identifiers for the dependency checking. */
+ r->savedstate = xmalloc (sizeof (struct cpp_savedstate));
+ r->savedstate->definedhash = htab_create (100, cpp_string_hash,
+ cpp_string_eq, NULL);
+ cpp_forall_identifiers (r, save_idents, r->savedstate);
+
+ /* Write out the list of defined identifiers. */
+ cpp_forall_identifiers (r, write_macdef, f);
+
+ return 0;
+}
+
+/* Calculate the 'hashsize' field of the saved state. */
+
+static int
+count_defs (pfile, hn, ss_p)
+ cpp_reader *pfile ATTRIBUTE_UNUSED;
+ cpp_hashnode *hn;
+ void *ss_p;
+{
+ struct cpp_savedstate *const ss = (struct cpp_savedstate *)ss_p;
+
+ switch (hn->type)
+ {
+ case NT_MACRO:
+ if (hn->flags & NODE_BUILTIN)
+ return 1;
+
+ /* else fall through. */
+
+ case NT_VOID:
+ {
+ struct cpp_string news;
+ void **slot;
+
+ news.len = NODE_LEN (hn);
+ news.text = NODE_NAME (hn);
+ slot = htab_find (ss->definedhash, &news);
+ if (slot == NULL)
+ ss->hashsize += NODE_LEN (hn) + 1;
+ }
+ return 1;
+
+ case NT_ASSERTION:
+ /* Not currently implemented. */
+ return 1;
+
+ default:
+ abort ();
+ }
+}
+
+/* Write the identifiers into 'definedstrs' of the state. */
+
+static int
+write_defs (pfile, hn, ss_p)
+ cpp_reader *pfile ATTRIBUTE_UNUSED;
+ cpp_hashnode *hn;
+ void *ss_p;
+{
+ struct cpp_savedstate *const ss = (struct cpp_savedstate *)ss_p;
+
+ switch (hn->type)
+ {
+ case NT_MACRO:
+ if (hn->flags & NODE_BUILTIN)
+ return 1;
+
+ /* else fall through. */
+
+ case NT_VOID:
+ {
+ struct cpp_string news;
+ void **slot;
+
+ news.len = NODE_LEN (hn);
+ news.text = NODE_NAME (hn);
+ slot = htab_find (ss->definedhash, &news);
+ if (slot == NULL)
+ {
+ memcpy (ss->definedstrs, NODE_NAME (hn), NODE_LEN (hn));
+ ss->definedstrs[NODE_LEN (hn)] = 0;
+ ss->definedstrs += NODE_LEN (hn) + 1;
+ }
+ }
+ return 1;
+
+ case NT_ASSERTION:
+ /* Not currently implemented. */
+ return 1;
+
+ default:
+ abort ();
+ }
+}
+
+/* Write out the remainder of the dependency information. This should be
+ called after the PCH is ready to be saved. */
+
+int
+cpp_write_pch_deps (r, f)
+ cpp_reader *r;
+ FILE *f;
+{
+ struct macrodef_struct z;
+ struct cpp_savedstate *const ss = r->savedstate;
+ unsigned char *definedstrs;
+
+ ss->hashsize = 0;
+
+ /* Write out the list of identifiers which have been seen and
+ weren't defined to anything previously. */
+ cpp_forall_identifiers (r, count_defs, ss);
+ definedstrs = ss->definedstrs = xmalloc (ss->hashsize);
+ cpp_forall_identifiers (r, write_defs, ss);
+ memset (&z, 0, sizeof (z));
+ z.definition_length = ss->hashsize;
+ if (fwrite (&z, sizeof (z), 1, f) != 1
+ || fwrite (definedstrs, ss->hashsize, 1, f) != 1)
+ {
+ cpp_errno (r, DL_ERROR, "while writing precompiled header");
+ return -1;
+ }
+ free (definedstrs);
+
+ /* Free the saved state. */
+ free (ss);
+ r->savedstate = NULL;
+ return 0;
+}
+
+/* Write out the definitions of the preprocessor, in a form suitable for
+ cpp_read_state. */
+
+int
+cpp_write_pch_state (r, f)
+ cpp_reader *r;
+ FILE *f;
+{
+ struct macrodef_struct z;
+
+ /* Write out the list of defined identifiers. */
+ cpp_forall_identifiers (r, write_macdef, f);
+ memset (&z, 0, sizeof (z));
+ if (fwrite (&z, sizeof (z), 1, f) != 1)
+ {
+ cpp_errno (r, DL_ERROR, "while writing precompiled header");
+ return -1;
+ }
+
+ if (!r->deps)
+ r->deps = deps_init ();
+
+ if (deps_save (r->deps, f) != 0)
+ {
+ cpp_errno (r, DL_ERROR, "while writing precompiled header");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Return nonzero if FD is a precompiled header which is consistent
+ with the preprocessor's current definitions. It will be consistent
+ when:
+
+ - anything that was defined just before the PCH was generated
+ is defined the same way now; and
+ - anything that was not defined then, but is defined now, was not
+ used by the PCH.
+
+ NAME is used to print warnings if `warn_invalid_pch' is set in the
+ reader's flags.
+*/
+
+int
+cpp_valid_state (r, name, fd)
+ cpp_reader *r;
+ const char *name;
+ int fd;
+{
+ struct macrodef_struct m;
+ size_t namebufsz = 256;
+ unsigned char *namebuf = xmalloc (namebufsz);
+ unsigned char *undeftab = NULL;
+ unsigned int i;
+
+ /* Read in the list of identifiers that must be defined
+ Check that they are defined in the same way. */
+ for (;;)
+ {
+ cpp_hashnode *h;
+ const unsigned char *newdefn;
+
+ if (read (fd, &m, sizeof (m)) != sizeof (m))
+ goto error;
+
+ if (m.name_length == 0)
+ break;
+
+ if (m.definition_length > namebufsz)
+ {
+ free (namebuf);
+ namebufsz = m.definition_length + 256;
+ namebuf = xmalloc (namebufsz);
+ }
+
+ if ((size_t)read (fd, namebuf, m.definition_length)
+ != m.definition_length)
+ goto error;
+
+ h = cpp_lookup (r, namebuf, m.name_length);
+ if (m.flags & NODE_POISONED
+ || h->type != NT_MACRO
+ || h->flags & NODE_POISONED)
+ {
+ if (CPP_OPTION (r, warn_invalid_pch))
+ cpp_error (r, DL_WARNING,
+ "%s: not used because `%.*s' not defined",
+ name, m.name_length, namebuf);
+ goto fail;
+ }
+
+ newdefn = cpp_macro_definition (r, h);
+
+ if (m.definition_length != ustrlen (newdefn)
+ || memcmp (namebuf, newdefn, m.definition_length) != 0)
+ {
+ if (CPP_OPTION (r, warn_invalid_pch))
+ cpp_error (r, DL_WARNING,
+ "%s: not used because `%.*s' defined as `%s' not `%.*s'",
+ name, m.name_length, namebuf, newdefn + m.name_length,
+ m.definition_length - m.name_length,
+ namebuf + m.name_length);
+ goto fail;
+ }
+ }
+ free (namebuf);
+ namebuf = NULL;
+
+ /* Read in the list of identifiers that must not be defined.
+ Check that they really aren't. */
+ undeftab = xmalloc (m.definition_length);
+ if ((size_t) read (fd, undeftab, m.definition_length) != m.definition_length)
+ goto error;
+ for (i = 0; i < m.definition_length; )
+ {
+ int l = ustrlen (undeftab + i);
+ cpp_hashnode *h;
+ h = cpp_lookup (r, undeftab + i, l);
+ if (h->type != NT_VOID
+ || h->flags & NODE_POISONED)
+ {
+ if (CPP_OPTION (r, warn_invalid_pch))
+ cpp_error (r, DL_WARNING, "%s: not used because `%s' is defined",
+ name, undeftab + i);
+ goto fail;
+ }
+ i += l + 1;
+ }
+ free (undeftab);
+
+ /* We win! */
+ return 0;
+
+ error:
+ cpp_errno (r, DL_ERROR, "while reading precompiled header");
+ return -1;
+
+ fail:
+ if (namebuf != NULL)
+ free (namebuf);
+ if (undeftab != NULL)
+ free (undeftab);
+ return 1;
+}
+
+/* Save all the existing macros and assertions.
+ This code assumes that there might be hundreds, but not thousands of
+ existing definitions. */
+
+struct save_macro_item {
+ struct save_macro_item *next;
+ struct cpp_hashnode macs[64];
+};
+
+struct save_macro_data
+{
+ struct save_macro_item *macros;
+ size_t count;
+ char **saved_pragmas;
+};
+
+/* Save the definition of a single macro, so that it will persist across
+ a PCH restore. */
+
+static int
+save_macros (r, h, data_p)
+ cpp_reader *r ATTRIBUTE_UNUSED;
+ cpp_hashnode *h;
+ void *data_p;
+{
+ struct save_macro_data *data = (struct save_macro_data *)data_p;
+ if (h->type != NT_VOID
+ && (h->flags & NODE_BUILTIN) == 0)
+ {
+ cpp_hashnode *save;
+ if (data->count == ARRAY_SIZE (data->macros->macs))
+ {
+ struct save_macro_item *d = data->macros;
+ data->macros = xmalloc (sizeof (struct save_macro_item));
+ data->macros->next = d;
+ data->count = 0;
+ }
+ save = data->macros->macs + data->count;
+ data->count++;
+ memcpy (save, h, sizeof (struct cpp_hashnode));
+ HT_STR (&save->ident) = xmemdup (HT_STR (HT_NODE (save)),
+ HT_LEN (HT_NODE (save)),
+ HT_LEN (HT_NODE (save)) + 1);
+ }
+ return 1;
+}
+
+/* Prepare to restore the state, by saving the currently-defined
+ macros in 'data'. */
+
+void
+cpp_prepare_state (r, data)
+ cpp_reader *r;
+ struct save_macro_data **data;
+{
+ struct save_macro_data *d = xmalloc (sizeof (struct save_macro_data));
+
+ d->macros = NULL;
+ d->count = ARRAY_SIZE (d->macros->macs);
+ cpp_forall_identifiers (r, save_macros, d);
+ d->saved_pragmas = _cpp_save_pragma_names (r);
+ *data = d;
+}
+
+/* Erase all the existing macros and assertions. */
+
+static int
+reset_ht (r, h, unused)
+ cpp_reader *r ATTRIBUTE_UNUSED;
+ cpp_hashnode *h;
+ void *unused ATTRIBUTE_UNUSED;
+{
+ if (h->type != NT_VOID
+ && (h->flags & NODE_BUILTIN) == 0)
+ {
+ h->type = NT_VOID;
+ memset (&h->value, 0, sizeof (h->value));
+ }
+ return 1;
+}
+
+/* Given a precompiled header that was previously determined to be valid,
+ apply all its definitions (and undefinitions) to the current state.
+ DEPNAME is passed to deps_restore. */
+
+int
+cpp_read_state (r, name, f, data)
+ cpp_reader *r;
+ const char *name;
+ FILE *f;
+ struct save_macro_data *data;
+{
+ struct macrodef_struct m;
+ size_t defnlen = 256;
+ unsigned char *defn = xmalloc (defnlen);
+ struct lexer_state old_state;
+ struct save_macro_item *d;
+ size_t i, mac_count;
+ int saved_line = r->line;
+
+ /* Erase all the existing hashtable entries for macros. At this
+ point, they're all from the PCH file, and their pointers won't be
+ valid. */
+ cpp_forall_identifiers (r, reset_ht, NULL);
+
+ /* Restore spec_nodes, which will be full of references to the old
+ hashtable entries and so will now be invalid. */
+ {
+ struct spec_nodes *s = &r->spec_nodes;
+ s->n_defined = cpp_lookup (r, DSC("defined"));
+ s->n_true = cpp_lookup (r, DSC("true"));
+ s->n_false = cpp_lookup (r, DSC("false"));
+ s->n__VA_ARGS__ = cpp_lookup (r, DSC("__VA_ARGS__"));
+ }
+
+ /* Run through the carefully-saved macros, insert them. */
+ d = data->macros;
+ mac_count = data->count;
+ while (d)
+ {
+ struct save_macro_item *nextd;
+ for (i = 0; i < mac_count; i++)
+ {
+ cpp_hashnode *h;
+
+ h = cpp_lookup (r, HT_STR (HT_NODE (&d->macs[i])),
+ HT_LEN (HT_NODE (&d->macs[i])));
+ h->type = d->macs[i].type;
+ h->flags = d->macs[i].flags;
+ h->value = d->macs[i].value;
+ free ((void *)HT_STR (HT_NODE (&d->macs[i])));
+ }
+ nextd = d->next;
+ free (d);
+ d = nextd;
+ mac_count = ARRAY_SIZE (d->macs);
+ }
+
+ _cpp_restore_pragma_names (r, data->saved_pragmas);
+
+ free (data);
+
+ old_state = r->state;
+
+ r->state.in_directive = 1;
+ r->state.prevent_expansion = 1;
+ r->state.angled_headers = 0;
+
+ /* Read in the identifiers that must be defined. */
+ for (;;)
+ {
+ cpp_hashnode *h;
+
+ if (fread (&m, sizeof (m), 1, f) != 1)
+ goto error;
+
+ if (m.name_length == 0)
+ break;
+
+ if (defnlen < m.definition_length + 1)
+ {
+ defnlen = m.definition_length + 256;
+ defn = xrealloc (defn, defnlen);
+ }
+
+ if (fread (defn, 1, m.definition_length, f) != m.definition_length)
+ goto error;
+ defn[m.definition_length] = '\0';
+
+ h = cpp_lookup (r, defn, m.name_length);
+
+ if (h->type == NT_MACRO)
+ _cpp_free_definition (h);
+ if (m.flags & NODE_POISONED)
+ h->flags |= NODE_POISONED | NODE_DIAGNOSTIC;
+ else if (m.name_length != m.definition_length)
+ {
+ if (cpp_push_buffer (r, defn + m.name_length,
+ m.definition_length - m.name_length,
+ true, 1) != NULL)
+ {
+ if (!_cpp_create_definition (r, h))
+ abort ();
+ _cpp_pop_buffer (r);
+ }
+ else
+ abort ();
+ }
+ }
+
+ r->state = old_state;
+ r->line = saved_line;
+ free (defn);
+ defn = NULL;
+
+ if (deps_restore (r->deps, f, CPP_OPTION (r, restore_pch_deps) ? name : NULL)
+ != 0)
+ goto error;
+
+ return 0;
+
+ error:
+ cpp_errno (r, DL_ERROR, "while reading precompiled header");
+ return -1;
+}
diff --git a/gcc/dbxout.c b/gcc/dbxout.c
index 5fcd28d8fc1..480ef821b70 100644
--- a/gcc/dbxout.c
+++ b/gcc/dbxout.c
@@ -137,57 +137,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#define STABS_GCC_MARKER "gcc2_compiled."
#endif
-/* Typical USG systems don't have stab.h, and they also have
- no use for DBX-format debugging info. */
-
-#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
-
-/* Nonzero if we have actually used any of the GDB extensions
- to the debugging format. The idea is that we use them for the
- first time only if there's a strong reason, but once we have done that,
- we use them whenever convenient. */
-
-static int have_used_extensions = 0;
-
-/* Number for the next N_SOL filename stabs label. The number 0 is reserved
- for the N_SO filename stabs label. */
-
-#if defined (DBX_DEBUGGING_INFO) && !defined (DBX_OUTPUT_SOURCE_FILENAME)
-static int source_label_number = 1;
-#endif
-
-#ifdef DEBUG_SYMS_TEXT
-#define FORCE_TEXT function_section (current_function_decl);
-#else
-#define FORCE_TEXT
-#endif
-
-#include "gstab.h"
-
-#define STAB_CODE_TYPE enum __stab_debug_code
-
-/* 1 if PARM is passed to this function in memory. */
-
-#define PARM_PASSED_IN_MEMORY(PARM) \
- (GET_CODE (DECL_INCOMING_RTL (PARM)) == MEM)
-
-/* A C expression for the integer offset value of an automatic variable
- (N_LSYM) having address X (an RTX). */
-#ifndef DEBUGGER_AUTO_OFFSET
-#define DEBUGGER_AUTO_OFFSET(X) \
- (GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0)
-#endif
-
-/* A C expression for the integer offset value of an argument (N_PSYM)
- having address X (an RTX). The nominal offset is OFFSET. */
-#ifndef DEBUGGER_ARG_OFFSET
-#define DEBUGGER_ARG_OFFSET(OFFSET, X) (OFFSET)
-#endif
-
-/* Stream for writing to assembler file. */
-
-static FILE *asmfile;
-
/* Last source file name mentioned in a NOTE insn. */
static const char *lastfile;
@@ -205,13 +154,11 @@ enum typestatus {TYPE_UNSEEN, TYPE_XREF, TYPE_DEFINED};
The file_number and type_number elements are used if DBX_USE_BINCL
is defined. */
-struct typeinfo
+struct typeinfo GTY(())
{
enum typestatus status;
-#ifdef DBX_USE_BINCL
int file_number;
int type_number;
-#endif
};
/* Vector recording information about C data types.
@@ -219,25 +166,23 @@ struct typeinfo
we assign it a number using next_type_number.
That is its index in this vector. */
-struct typeinfo *typevec;
+static GTY ((length ("typevec_len"))) struct typeinfo *typevec;
/* Number of elements of space allocated in `typevec'. */
-static int typevec_len;
+static GTY(()) int typevec_len;
/* In dbx output, each type gets a unique number.
This is the number for the next type output.
The number, once assigned, is in the TYPE_SYMTAB_ADDRESS field. */
-static int next_type_number;
-
-#ifdef DBX_USE_BINCL
+static GTY(()) int next_type_number;
/* When using N_BINCL in dbx output, each type number is actually a
pair of the file number and the type number within the file.
This is a stack of input files. */
-struct dbx_file
+struct dbx_file GTY(())
{
struct dbx_file *next;
int file_number;
@@ -246,13 +191,62 @@ struct dbx_file
/* This is the top of the stack. */
-static struct dbx_file *current_file;
+static GTY(()) struct dbx_file *current_file;
/* This is the next file number to use. */
-static int next_file_number;
+static GTY(()) int next_file_number;
+
+/* Typical USG systems don't have stab.h, and they also have
+ no use for DBX-format debugging info. */
+
+#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
+
+/* Nonzero if we have actually used any of the GDB extensions
+ to the debugging format. The idea is that we use them for the
+ first time only if there's a strong reason, but once we have done that,
+ we use them whenever convenient. */
+
+static int have_used_extensions = 0;
+
+/* Number for the next N_SOL filename stabs label. The number 0 is reserved
+ for the N_SO filename stabs label. */
+
+#if defined (DBX_DEBUGGING_INFO) && !defined (DBX_OUTPUT_SOURCE_FILENAME)
+static int source_label_number = 1;
+#endif
+
+#ifdef DEBUG_SYMS_TEXT
+#define FORCE_TEXT function_section (current_function_decl);
+#else
+#define FORCE_TEXT
+#endif
+
+#include "gstab.h"
+
+#define STAB_CODE_TYPE enum __stab_debug_code
+
+/* 1 if PARM is passed to this function in memory. */
+
+#define PARM_PASSED_IN_MEMORY(PARM) \
+ (GET_CODE (DECL_INCOMING_RTL (PARM)) == MEM)
-#endif /* DBX_USE_BINCL */
+/* A C expression for the integer offset value of an automatic variable
+ (N_LSYM) having address X (an RTX). */
+#ifndef DEBUGGER_AUTO_OFFSET
+#define DEBUGGER_AUTO_OFFSET(X) \
+ (GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0)
+#endif
+
+/* A C expression for the integer offset value of an argument (N_PSYM)
+ having address X (an RTX). The nominal offset is OFFSET. */
+#ifndef DEBUGGER_ARG_OFFSET
+#define DEBUGGER_ARG_OFFSET(OFFSET, X) (OFFSET)
+#endif
+
+/* Stream for writing to assembler file. */
+
+static FILE *asmfile;
/* These variables are for dbxout_symbol to communicate to
dbxout_finish_symbol.
@@ -425,7 +419,7 @@ dbxout_init (input_file_name)
asmfile = asm_out_file;
typevec_len = 100;
- typevec = (struct typeinfo *) xcalloc (typevec_len, sizeof typevec[0]);
+ typevec = (struct typeinfo *) ggc_calloc (typevec_len, sizeof typevec[0]);
/* Convert Ltext into the appropriate format for local labels in case
the system doesn't insert underscores in front of user generated
@@ -484,7 +478,7 @@ dbxout_init (input_file_name)
next_type_number = 1;
#ifdef DBX_USE_BINCL
- current_file = (struct dbx_file *) xmalloc (sizeof *current_file);
+ current_file = (struct dbx_file *) ggc_alloc (sizeof *current_file);
current_file->next = NULL;
current_file->file_number = 0;
current_file->next_type_number = 1;
@@ -541,7 +535,7 @@ dbxout_start_source_file (line, filename)
const char *filename ATTRIBUTE_UNUSED;
{
#ifdef DBX_USE_BINCL
- struct dbx_file *n = (struct dbx_file *) xmalloc (sizeof *n);
+ struct dbx_file *n = (struct dbx_file *) ggc_alloc (sizeof *n);
n->next = current_file;
n->file_number = next_file_number++;
@@ -560,12 +554,8 @@ dbxout_end_source_file (line)
unsigned int line ATTRIBUTE_UNUSED;
{
#ifdef DBX_USE_BINCL
- struct dbx_file *next;
-
fprintf (asmfile, "%s%d,0,0,0\n", ASM_STABN_OP, N_EINCL);
- next = current_file->next;
- free (current_file);
- current_file = next;
+ current_file = current_file->next;
#endif
}
@@ -1149,8 +1139,9 @@ dbxout_type (type, full)
if (next_type_number == typevec_len)
{
typevec
- = (struct typeinfo *) xrealloc (typevec,
- typevec_len * 2 * sizeof typevec[0]);
+ = (struct typeinfo *) ggc_realloc (typevec,
+ (typevec_len * 2
+ * sizeof typevec[0]));
memset ((char *) (typevec + typevec_len), 0,
typevec_len * sizeof typevec[0]);
typevec_len *= 2;
@@ -3008,3 +2999,5 @@ dbxout_begin_function (decl)
#endif /* DBX_DEBUGGING_INFO */
#endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */
+
+#include "gt-dbxout.h"
diff --git a/gcc/doc/cppopts.texi b/gcc/doc/cppopts.texi
index 74fe8be5b7d..95311a86d4e 100644
--- a/gcc/doc/cppopts.texi
+++ b/gcc/doc/cppopts.texi
@@ -301,6 +301,17 @@ a dependency output file as a side-effect of the compilation process.
Like @option{-MD} except mention only user header files, not system
-header files.
+@ifclear cppmanual
+@item -fpch-deps
+@opindex fpch-deps
+When using precompiled headers (@pxref{Precompiled Headers}), this flag
+will cause the dependency-output flags to also list the files from the
+precompiled header's dependencies. If not specified only the
+precompiled header would be listed and not the files that were used to
+create it because those files are not consulted when a precompiled
+header is used.
+
+@end ifclear
@item -x c
@itemx -x c++
@itemx -x objective-c
diff --git a/gcc/doc/gty.texi b/gcc/doc/gty.texi
index 55deef24f69..ed7d3d2c1a1 100644
--- a/gcc/doc/gty.texi
+++ b/gcc/doc/gty.texi
@@ -10,7 +10,8 @@
GCC uses some fairly sophisticated memory management techniques, which
involve determining information about GCC's data structures from GCC's
-source code and using this information to perform garbage collection.
+source code and using this information to perform garbage collection and
+implement precompiled headers.
A full C parser would be too overcomplicated for this task, so a limited
subset of C is interpreted and special markers are used to determine
@@ -227,6 +228,39 @@ this field is always @code{NULL}. This is used to avoid requiring
backends to define certain optional structures. It doesn't work with
language frontends.
+@findex chain_next
+@findex chain_prev
+@item chain_next
+@itemx chain_prev
+
+It's helpful for the type machinery to know if objects are often
+chained together in long lists; this lets it generate code that uses
+less stack space by iterating along the list instead of recursing down
+it. @code{chain_next} is an expression for the next item in the list,
+@code{chain_prev} is an expression for the previous item. The
+machinery requires that taking the next item of the previous item
+gives the original item.
+
+@findex reorder
+@item reorder
+
+Some data structures depend on the relative ordering of pointers. If
+the type machinery needs to change that ordering, it will call the
+function referenced by the @code{reorder} option, before changing the
+pointers in the object that's pointed to by the field the option
+applies to. The function must be of the type @code{void ()(void *,
+void *, gt_pointer_operator, void *)}. The second parameter is the
+pointed-to object; the third parameter is a routine that, given a
+pointer, can update it to its new value. The fourth parameter is a
+cookie to be passed to the third parameter. The first parameter is
+the structure that contains the object, or the object itself if it is
+a structure.
+
+No data structure may depend on the absolute value of pointers. Even
+relying on relative orderings and using @code{reorder} functions can
+be expensive. It is better to depend on properties of the data, like
+an ID number or the hash of a string instead.
+
@findex special
@item special
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 8b3e365a550..bfbdd3ebbc2 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -141,6 +141,7 @@ only one of these two forms, whichever one is not the default.
* Code Gen Options:: Specifying conventions for function calls, data layout
and register usage.
* Environment Variables:: Env vars that affect GCC.
+* Precompiled Headers:: Compiling a header once, and using it many times.
* Running Protoize:: Automatically adding or removing function prototypes.
@end menu
@@ -220,7 +221,7 @@ in the following sections.
-Wimplicit -Wimplicit-int @gol
-Wimplicit-function-declaration @gol
-Werror-implicit-function-declaration @gol
--Wimport -Winline -Wno-endif-labels @gol
+-Wimport -Winline -Winvalid-pch -Wno-endif-labels @gol
-Wlarger-than-@var{len} -Wlong-long @gol
-Wmain -Wmissing-braces @gol
-Wmissing-format-attribute -Wmissing-noreturn @gol
@@ -767,7 +768,7 @@ Objective-C source code. Note that you must link with the library
Objective-C source code which should not be preprocessed.
@item @var{file}.h
-C header file (not to be compiled or linked).
+C or C++ header file to be turned into a precompiled header.
@item @var{file}.cc
@itemx @var{file}.cp
@@ -780,6 +781,10 @@ C++ source code which must be preprocessed. Note that in @samp{.cxx},
the last two letters must both be literally @samp{x}. Likewise,
@samp{.C} refers to a literal capital C@.
+@item @var{file}.hh
+@itemx @var{file}.H
+C++ header file to be turned into a precompiled header.
+
@item @var{file}.f
@itemx @var{file}.for
@itemx @var{file}.FOR
@@ -843,7 +848,7 @@ name suffix). This option applies to all following input files until
the next @option{-x} option. Possible values for @var{language} are:
@example
c c-header cpp-output
-c++ c++-cpp-output
+c++ c++-header c++-cpp-output
objective-c objc-cpp-output
assembler assembler-with-cpp
ada
@@ -965,22 +970,24 @@ Display the version number and copyrights of the invoked GCC.
@cindex suffixes for C++ source
@cindex C++ source file suffixes
C++ source files conventionally use one of the suffixes @samp{.C},
-@samp{.cc}, @samp{.cpp}, @samp{.CPP}, @samp{.c++}, @samp{.cp}, or @samp{.cxx};
+@samp{.cc}, @samp{.cpp}, @samp{.CPP}, @samp{.c++}, @samp{.cp}, or
+@samp{.cxx}; C++ header files often use @samp{.hh} or @samp{.H}; and
preprocessed C++ files use the suffix @samp{.ii}. GCC recognizes
files with these names and compiles them as C++ programs even if you
-call the compiler the same way as for compiling C programs (usually with
-the name @command{gcc}).
+call the compiler the same way as for compiling C programs (usually
+with the name @command{gcc}).
@findex g++
@findex c++
However, C++ programs often require class libraries as well as a
compiler that understands the C++ language---and under some
-circumstances, you might want to compile programs from standard input,
-or otherwise without a suffix that flags them as C++ programs.
-@command{g++} is a program that calls GCC with the default language
-set to C++, and automatically specifies linking against the C++
-library. On many systems, @command{g++} is also
-installed with the name @command{c++}.
+circumstances, you might want to compile programs or header files from
+standard input, or otherwise without a suffix that flags them as C++
+programs. You might also like to precompile a C header file with a
+@samp{.h} extension to be used in C++ compilations. @command{g++} is a
+program that calls GCC with the default language set to C++, and
+automatically specifies linking against the C++ library. On many
+systems, @command{g++} is also installed with the name @command{c++}.
@cindex invoking @command{g++}
When you compile C++ programs, you may specify many of the same
@@ -2800,6 +2807,11 @@ code is to provide behavior which is selectable at compile-time.
@opindex Winline
Warn if a function can not be inlined and it was declared as inline.
+@item -Winvalid-pch
+@opindex Winvalid-pch
+Warn if a precompiled header (@pxref{Precompiled Headers}) is found in
+the search path but can't be used.
+
@item -Wlong-long
@opindex Wlong-long
@opindex Wno-long-long
@@ -10924,6 +10936,104 @@ preprocessor.
@c man end
+@node Precompiled Headers
+@section Using Precompiled Headers
+@cindex precompiled headers
+@cindex speed of compilation
+
+Often large projects have many header files that are included in every
+source file. The time the compiler takes to process these header files
+over and over again can account for nearly all of the time required to
+build the project. To make builds faster, GCC allows users to
+`precompile' a header file; then, if builds can use the precompiled
+header file they will be much faster.
+
+To create a precompiled header file, simply compile it as you would any
+other file, if necessary using the @option{-x} option to make the driver
+treat it as a C or C++ header file. You will probably want to use a
+tool like @command{make} to keep the precompiled header up-to-date when
+the headers it contains change.
+
+A precompiled header file will be searched for when @code{#include} is
+seen in the compilation. As it searches for the included file
+(@pxref{Search Path,,Search Path,cpp.info,The C Preprocessor}) the
+compiler looks for a precompiled header in each directory just before it
+looks for the include file in that directory. The name searched for is
+the name specified in the @code{#include} with @samp{.pch} appended. If
+the precompiled header file can't be used, it is ignored.
+
+For instance, if you have @code{#include "all.h"}, and you have
+@file{all.h.pch} in the same directory as @file{all.h}, then the
+precompiled header file will be used if possible, and the original
+header will be used otherwise.
+
+Alternatively, you might decide to put the precompiled header file in a
+directory and use @option{-I} to ensure that directory is searched
+before (or instead of) the directory containing the original header.
+Then, if you want to check that the precompiled header file is always
+used, you can put a file of the same name as the original header in this
+directory containing an @code{#error} command.
+
+This also works with @option{-include}. So yet another way to use
+precompiled headers, good for projects not designed with precompiled
+header files in mind, is to simply take most of the header files used by
+a project, include them from another header file, precompile that header
+file, and @option{-include} the precompiled header. If the header files
+have guards against multiple inclusion, they will be skipped because
+they've already been included (in the precompiled header).
+
+If you need to precompile the same header file for different
+languages, targets, or compiler options, you can instead make a
+@emph{directory} named like @file{all.h.pch}, and put each precompiled
+header in the directory. (It doesn't matter what you call the files
+in the directory, every precompiled header in the directory will be
+considered.) The first precompiled header encountered in the
+directory that is valid for this compilation will be used; they're
+searched in no particular order.
+
+There are many other possibilities, limited only by your imagination,
+good sense, and the constraints of your build system.
+
+A precompiled header file can be used only when these conditions apply:
+
+@itemize
+@item
+Only one precompiled header can be used in a particular compilation.
+@item
+A precompiled header can't be used once the first C token is seen. You
+can have preprocessor directives before a precompiled header; you can
+even include a precompiled header from inside another header, so long as
+there are no C tokens before the @code{#include}.
+@item
+The precompiled header file must be produced for the same language as
+the current compilation. You can't use a C precompiled header for a C++
+compilation.
+@item
+The precompiled header file must be produced by the same compiler
+version and configuration as the current compilation is using.
+The easiest way to guarantee this is to use the same compiler binary
+for creating and using precompiled headers.
+@item
+Any macros defined before the precompiled header (including with
+@option{-D}) must either be defined in the same way as when the
+precompiled header was generated, or must not affect the precompiled
+header, which usually means that the they don't appear in the
+precompiled header at all.
+@item
+Certain command-line options must be defined in the same way as when the
+precompiled header was generated. At present, it's not clear which
+options are safe to change and which are not; the safest choice is to
+use exactly the same options when generating and using the precompiled
+header.
+@end itemize
+
+For all of these but the last, the compiler will automatically ignore
+the precompiled header if the conditions aren't met. For the last item,
+some option changes will cause the precompiled header to be rejected,
+but not all incompatible option combinations have yet been found. If
+you find a new incompatible combination, please consider filing a bug
+report, see @ref{Bugs}.
+
@node Running Protoize
@section Running Protoize
diff --git a/gcc/doc/passes.texi b/gcc/doc/passes.texi
index c47433eccfc..8a96a692461 100644
--- a/gcc/doc/passes.texi
+++ b/gcc/doc/passes.texi
@@ -1,4 +1,4 @@
-@c Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+@c Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2002,
@c 1999, 2000, 2001 Free Software Foundation, Inc.
@c This is part of the GCC manual.
@c For copying conditions, see the file gcc.texi.
@@ -73,54 +73,22 @@ performed by cpplib, which is covered in separate documentation. In
particular, the internals are covered in @xref{Top, ,Cpplib internals,
cppinternals, Cpplib Internals}.
-@c Avoiding overfull is tricky here.
-The source files to parse C are
-@file{c-convert.c},
-@file{c-decl.c},
-@file{c-errors.c},
-@file{c-lang.c},
-@file{c-objc-common.c},
-@file{c-parse.in},
-@file{c-aux-info.c},
-and
-@file{c-typeck.c},
-along with a header file
-@file{c-tree.h}
-and some files shared with Objective-C and C++.
-
-The source files for parsing C++ are in @file{cp/}.
-They are @file{parse.y},
-@file{class.c},
-@file{cvt.c}, @file{decl.c}, @file{decl2.c},
-@file{except.c},
-@file{expr.c}, @file{init.c}, @file{lex.c},
-@file{method.c}, @file{ptree.c},
-@file{search.c}, @file{spew.c},
-@file{semantics.c}, @file{tree.c},
-@file{typeck2.c}, and
-@file{typeck.c}, along with header files @file{cp-tree.def},
-@file{cp-tree.h}, and @file{decl.h}.
-
-The special source files for parsing Objective-C are in @file{objc/}.
-They are @file{objc-act.c}, @file{objc-tree.def}, and @file{objc-act.h}.
-Certain C-specific files are used for this as well.
-
-The files
-@file{c-common.c},
+The source files to parse C are found in the toplevel directory, and
+by convention are named @file{c-*}. Some of these are also used by
+the other C-like languages: @file{c-common.c},
@file{c-common.def},
@file{c-format.c},
@file{c-opts.c},
@file{c-pragma.c},
@file{c-semantics.c},
-and
@file{c-lex.c},
-along with header files
@file{c-common.h},
@file{c-dump.h},
and
@file{c-pragma.h},
-are also used for all of the above languages.
+Files specific to each language are in subdirectories named after the
+language in question, like @file{ada}, @file{objc}, @file{cp} (for C++).
@cindex Tree optimization
@item
diff --git a/gcc/dwarf2asm.c b/gcc/dwarf2asm.c
index 777ba8da71c..396c2cdd355 100644
--- a/gcc/dwarf2asm.c
+++ b/gcc/dwarf2asm.c
@@ -688,12 +688,12 @@ dw2_asm_output_delta_sleb128 VPARAMS ((const char *lab1 ATTRIBUTE_UNUSED,
VA_CLOSE (ap);
}
-static int mark_indirect_pool_entry PARAMS ((splay_tree_node, void *));
-static void mark_indirect_pool PARAMS ((PTR arg));
static rtx dw2_force_const_mem PARAMS ((rtx));
static int dw2_output_indirect_constant_1 PARAMS ((splay_tree_node, void *));
-static splay_tree indirect_pool;
+static GTY((param1_is (char *), param2_is (tree))) splay_tree indirect_pool;
+
+static GTY(()) int dw2_const_labelno;
#if defined(HAVE_GAS_HIDDEN) && defined(SUPPORTS_ONE_ONLY)
# define USE_LINKONCE_INDIRECT 1
@@ -701,26 +701,6 @@ static splay_tree indirect_pool;
# define USE_LINKONCE_INDIRECT 0
#endif
-/* Mark all indirect constants for GC. */
-
-static int
-mark_indirect_pool_entry (node, data)
- splay_tree_node node;
- void* data ATTRIBUTE_UNUSED;
-{
- ggc_mark_tree ((tree) node->value);
- return 0;
-}
-
-/* Mark all indirect constants for GC. */
-
-static void
-mark_indirect_pool (arg)
- PTR arg ATTRIBUTE_UNUSED;
-{
- splay_tree_foreach (indirect_pool, mark_indirect_pool_entry, NULL);
-}
-
/* Put X, a SYMBOL_REF, in memory. Return a SYMBOL_REF to the allocated
memory. Differs from force_const_mem in that a single pool is used for
the entire unit of translation, and the memory is not guaranteed to be
@@ -735,10 +715,7 @@ dw2_force_const_mem (x)
tree decl;
if (! indirect_pool)
- {
- indirect_pool = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
- ggc_add_root (&indirect_pool, 1, sizeof indirect_pool, mark_indirect_pool);
- }
+ indirect_pool = splay_tree_new_ggc (splay_tree_compare_pointers);
if (GET_CODE (x) != SYMBOL_REF)
abort ();
@@ -765,11 +742,10 @@ dw2_force_const_mem (x)
}
else
{
- extern int const_labelno;
char label[32];
- ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno);
- ++const_labelno;
+ ASM_GENERATE_INTERNAL_LABEL (label, "LDFCM", dw2_const_labelno);
+ ++dw2_const_labelno;
id = get_identifier (label);
decl = build_decl (VAR_DECL, id, ptr_type_node);
DECL_ARTIFICIAL (decl) = 1;
@@ -906,3 +882,5 @@ dw2_asm_output_encoded_addr_rtx VPARAMS ((int encoding,
VA_CLOSE (ap);
}
+
+#include "gt-dwarf2asm.h"
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index c93142069b3..38d34002533 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -63,7 +63,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "debug.h"
#include "target.h"
#include "langhooks.h"
-#include "hashtable.h"
#include "hashtab.h"
#ifdef DWARF2_DEBUGGING_INFO
@@ -163,8 +162,6 @@ static GTY(()) varray_type incomplete_types;
define type declaration DIE's. */
static GTY(()) varray_type decl_scope_table;
-#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
-
/* How to start an assembler comment. */
#ifndef ASM_COMMENT_START
#define ASM_COMMENT_START ";#"
@@ -179,21 +176,31 @@ typedef union dw_cfi_oprnd_struct *dw_cfi_oprnd_ref;
and address fields are provided as possible operands;
their use is selected by the opcode field. */
-typedef union dw_cfi_oprnd_struct
+enum dw_cfi_oprnd_type {
+ dw_cfi_oprnd_unused,
+ dw_cfi_oprnd_reg_num,
+ dw_cfi_oprnd_offset,
+ dw_cfi_oprnd_addr,
+ dw_cfi_oprnd_loc
+};
+
+typedef union dw_cfi_oprnd_struct GTY(())
{
- unsigned long dw_cfi_reg_num;
- long int dw_cfi_offset;
- const char *dw_cfi_addr;
- struct dw_loc_descr_struct *dw_cfi_loc;
+ unsigned long GTY ((tag ("dw_cfi_oprnd_reg_num"))) dw_cfi_reg_num;
+ long int GTY ((tag ("dw_cfi_oprnd_offset"))) dw_cfi_offset;
+ const char * GTY ((tag ("dw_cfi_oprnd_addr"))) dw_cfi_addr;
+ struct dw_loc_descr_struct * GTY ((tag ("dw_cfi_oprnd_loc"))) dw_cfi_loc;
}
dw_cfi_oprnd;
-typedef struct dw_cfi_struct
+typedef struct dw_cfi_struct GTY(())
{
dw_cfi_ref dw_cfi_next;
enum dwarf_call_frame_info dw_cfi_opc;
- dw_cfi_oprnd dw_cfi_oprnd1;
- dw_cfi_oprnd dw_cfi_oprnd2;
+ dw_cfi_oprnd GTY ((desc ("dw_cfi_oprnd1_desc (%1.dw_cfi_opc)")))
+ dw_cfi_oprnd1;
+ dw_cfi_oprnd GTY ((desc ("dw_cfi_oprnd2_desc (%1.dw_cfi_opc)")))
+ dw_cfi_oprnd2;
}
dw_cfi_node;
@@ -202,7 +209,7 @@ dw_cfi_node;
It can now be either REG + CFA_OFFSET or *(REG + BASE_OFFSET) + CFA_OFFSET.
Instead of passing around REG and OFFSET, we pass a copy
of this structure. */
-typedef struct cfa_loc
+typedef struct cfa_loc GTY(())
{
unsigned long reg;
long offset;
@@ -216,7 +223,7 @@ typedef struct cfa_loc
CIE obviates the need to keep track of multiple CIE's
in the DWARF generation routines below. */
-typedef struct dw_fde_struct
+typedef struct dw_fde_struct GTY(())
{
const char *dw_fde_begin;
const char *dw_fde_current_label;
@@ -267,7 +274,7 @@ dw_fde_node;
/* A pointer to the base of a table that contains frame description
information for each routine. */
-static dw_fde_ref fde_table;
+static GTY((length ("fde_table_allocated"))) dw_fde_ref fde_table;
/* Number of elements currently allocated for fde_table. */
static unsigned fde_table_allocated;
@@ -280,7 +287,7 @@ static unsigned fde_table_in_use;
#define FDE_TABLE_INCREMENT 256
/* A list of call frame insns for the CIE. */
-static dw_cfi_ref cie_cfi_head;
+static GTY(()) dw_cfi_ref cie_cfi_head;
/* Some DWARF extensions (e.g., MIPS/SGI) implement a subprogram
attribute that accelerates the lookup of the FDE associated
@@ -288,16 +295,20 @@ static dw_cfi_ref cie_cfi_head;
associated with the current function (body) definition. */
static unsigned current_funcdef_fde;
-struct ht *debug_str_hash;
-
-struct indirect_string_node
+struct indirect_string_node GTY(())
{
- struct ht_identifier id;
+ const char *str;
unsigned int refcount;
unsigned int form;
char *label;
};
+static GTY ((param_is (struct indirect_string_node))) htab_t debug_str_hash;
+
+static GTY(()) int dw2_string_counter;
+
+#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
+
/* Forward declarations for functions defined in this file. */
static char *stripattributes PARAMS ((const char *));
@@ -313,6 +324,10 @@ static void reg_save PARAMS ((const char *, unsigned,
static void initial_return_save PARAMS ((rtx));
static long stack_adjust_offset PARAMS ((rtx));
static void output_cfi PARAMS ((dw_cfi_ref, dw_fde_ref, int));
+static enum dw_cfi_oprnd_type dw_cfi_oprnd1_desc
+ PARAMS ((enum dwarf_call_frame_info cfi));
+static enum dw_cfi_oprnd_type dw_cfi_oprnd2_desc
+ PARAMS ((enum dwarf_call_frame_info cfi));
static void output_call_frame_info PARAMS ((int));
static void dwarf2out_stack_adjust PARAMS ((rtx));
static void queue_reg_save PARAMS ((const char *, rtx, long));
@@ -515,7 +530,7 @@ dwarf_cfi_name (cfi_opc)
static inline dw_cfi_ref
new_cfi ()
{
- dw_cfi_ref cfi = (dw_cfi_ref) xmalloc (sizeof (dw_cfi_node));
+ dw_cfi_ref cfi = (dw_cfi_ref) ggc_alloc (sizeof (dw_cfi_node));
cfi->dw_cfi_next = NULL;
cfi->dw_cfi_oprnd1.dw_cfi_reg_num = 0;
@@ -1086,18 +1101,22 @@ dwarf2out_stack_adjust (insn)
dwarf2out_args_size (label, args_size);
}
+#endif
+
/* We delay emitting a register save until either (a) we reach the end
of the prologue or (b) the register is clobbered. This clusters
register saves so that there are fewer pc advances. */
-struct queued_reg_save
+struct queued_reg_save GTY(())
{
struct queued_reg_save *next;
rtx reg;
long cfa_offset;
};
-static struct queued_reg_save *queued_reg_saves;
+static GTY(()) struct queued_reg_save *queued_reg_saves;
+
+#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
static const char *last_reg_save_label;
static void
@@ -1106,7 +1125,7 @@ queue_reg_save (label, reg, offset)
rtx reg;
long offset;
{
- struct queued_reg_save *q = (struct queued_reg_save *) xmalloc (sizeof (*q));
+ struct queued_reg_save *q = ggc_alloc (sizeof (*q));
q->next = queued_reg_saves;
q->reg = reg;
@@ -1125,7 +1144,6 @@ flush_queued_reg_saves ()
{
dwarf2out_reg_save (last_reg_save_label, REGNO (q->reg), q->cfa_offset);
next = q->next;
- free (q);
}
queued_reg_saves = NULL;
@@ -1678,6 +1696,78 @@ dwarf2out_frame_debug (insn)
dwarf2out_frame_debug_expr (insn, label);
}
+#endif
+
+/* Describe for the GTY machinery what parts of dw_cfi_oprnd1 are used. */
+
+static enum dw_cfi_oprnd_type
+dw_cfi_oprnd1_desc (cfi)
+ enum dwarf_call_frame_info cfi;
+{
+ switch (cfi)
+ {
+ case DW_CFA_nop:
+ case DW_CFA_GNU_window_save:
+ return dw_cfi_oprnd_unused;
+
+ case DW_CFA_set_loc:
+ case DW_CFA_advance_loc1:
+ case DW_CFA_advance_loc2:
+ case DW_CFA_advance_loc4:
+ case DW_CFA_MIPS_advance_loc8:
+ return dw_cfi_oprnd_addr;
+
+ case DW_CFA_offset:
+ case DW_CFA_offset_extended:
+ case DW_CFA_def_cfa:
+ case DW_CFA_offset_extended_sf:
+ case DW_CFA_def_cfa_sf:
+ case DW_CFA_restore_extended:
+ case DW_CFA_undefined:
+ case DW_CFA_same_value:
+ case DW_CFA_def_cfa_register:
+ case DW_CFA_register:
+ return dw_cfi_oprnd_reg_num;
+
+ case DW_CFA_def_cfa_offset:
+ case DW_CFA_GNU_args_size:
+ case DW_CFA_def_cfa_offset_sf:
+ return dw_cfi_oprnd_offset;
+
+ case DW_CFA_def_cfa_expression:
+ case DW_CFA_expression:
+ return dw_cfi_oprnd_loc;
+
+ default:
+ abort ();
+ }
+}
+
+/* Describe for the GTY machinery what parts of dw_cfi_oprnd2 are used. */
+
+static enum dw_cfi_oprnd_type
+dw_cfi_oprnd2_desc (cfi)
+ enum dwarf_call_frame_info cfi;
+{
+ switch (cfi)
+ {
+ case DW_CFA_def_cfa:
+ case DW_CFA_def_cfa_sf:
+ case DW_CFA_offset:
+ case DW_CFA_offset_extended_sf:
+ case DW_CFA_offset_extended:
+ return dw_cfi_oprnd_offset;
+
+ case DW_CFA_register:
+ return dw_cfi_oprnd_reg_num;
+
+ default:
+ return dw_cfi_oprnd_unused;
+ }
+}
+
+#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
+
/* Output a Call Frame Information opcode and its operand(s). */
static void
@@ -2118,9 +2208,10 @@ dwarf2out_begin_prologue (line, file)
if (fde_table_in_use == fde_table_allocated)
{
fde_table_allocated += FDE_TABLE_INCREMENT;
- fde_table
- = (dw_fde_ref) xrealloc (fde_table,
- fde_table_allocated * sizeof (dw_fde_node));
+ fde_table = ggc_realloc (fde_table,
+ fde_table_allocated * sizeof (dw_fde_node));
+ memset (fde_table + fde_table_in_use, 0,
+ FDE_TABLE_INCREMENT * sizeof (dw_fde_node));
}
/* Record the FDE associated with this function. */
@@ -2172,7 +2263,8 @@ void
dwarf2out_frame_init ()
{
/* Allocate the initial hunk of the fde_table. */
- fde_table = (dw_fde_ref) xcalloc (FDE_TABLE_INCREMENT, sizeof (dw_fde_node));
+ fde_table = (dw_fde_ref) ggc_alloc_cleared (FDE_TABLE_INCREMENT
+ * sizeof (dw_fde_node));
fde_table_allocated = FDE_TABLE_INCREMENT;
fde_table_in_use = 0;
@@ -2196,6 +2288,7 @@ dwarf2out_frame_finish ()
if (! USING_SJLJ_EXCEPTIONS && (flag_unwind_tables || flag_exceptions))
output_call_frame_info (1);
}
+#endif
/* And now, the subset of the debugging information support code necessary
for emitting location expressions. */
@@ -2214,7 +2307,7 @@ typedef struct dw_loc_list_struct *dw_loc_list_ref;
can take on several forms. The forms that are used in this
implementation are listed below. */
-typedef enum
+enum dw_val_class
{
dw_val_class_addr,
dw_val_class_offset,
@@ -2231,13 +2324,12 @@ typedef enum
dw_val_class_lbl_id,
dw_val_class_lbl_offset,
dw_val_class_str
-}
-dw_val_class;
+};
/* Describe a double word constant value. */
/* ??? Every instance of long_long in the code really means CONST_DOUBLE. */
-typedef struct dw_long_long_struct
+typedef struct dw_long_long_struct GTY(())
{
unsigned long hi;
unsigned long low;
@@ -2246,9 +2338,9 @@ dw_long_long_const;
/* Describe a floating point constant value. */
-typedef struct dw_fp_struct
+typedef struct dw_fp_struct GTY(())
{
- long *array;
+ long * GTY((length ("%h.length"))) array;
unsigned length;
}
dw_float_const;
@@ -2256,37 +2348,37 @@ dw_float_const;
/* The dw_val_node describes an attribute's value, as it is
represented internally. */
-typedef struct dw_val_struct
+typedef struct dw_val_struct GTY(())
{
- dw_val_class val_class;
- union
+ enum dw_val_class val_class;
+ union dw_val_struct_union
{
- rtx val_addr;
- long unsigned val_offset;
- dw_loc_list_ref val_loc_list;
- dw_loc_descr_ref val_loc;
- long int val_int;
- long unsigned val_unsigned;
- dw_long_long_const val_long_long;
- dw_float_const val_float;
- struct
+ rtx GTY ((tag ("dw_val_class_addr"))) val_addr;
+ long unsigned GTY ((tag ("dw_val_class_offset"))) val_offset;
+ dw_loc_list_ref GTY ((tag ("dw_val_class_loc_list"))) val_loc_list;
+ dw_loc_descr_ref GTY ((tag ("dw_val_class_loc"))) val_loc;
+ long int GTY ((default (""))) val_int;
+ long unsigned GTY ((tag ("dw_val_class_unsigned_const"))) val_unsigned;
+ dw_long_long_const GTY ((tag ("dw_val_class_long_long"))) val_long_long;
+ dw_float_const GTY ((tag ("dw_val_class_float"))) val_float;
+ struct dw_val_die_union
{
dw_die_ref die;
int external;
- } val_die_ref;
- unsigned val_fde_index;
- struct indirect_string_node *val_str;
- char *val_lbl_id;
- unsigned char val_flag;
+ } GTY ((tag ("dw_val_class_die_ref"))) val_die_ref;
+ unsigned GTY ((tag ("dw_val_class_fde_ref"))) val_fde_index;
+ struct indirect_string_node * GTY ((tag ("dw_val_class_str"))) val_str;
+ char * GTY ((tag ("dw_val_class_lbl_id"))) val_lbl_id;
+ unsigned char GTY ((tag ("dw_val_class_flag"))) val_flag;
}
- v;
+ GTY ((desc ("%1.val_class"))) v;
}
dw_val_node;
/* Locations in memory are described using a sequence of stack machine
operations. */
-typedef struct dw_loc_descr_struct
+typedef struct dw_loc_descr_struct GTY(())
{
dw_loc_descr_ref dw_loc_next;
enum dwarf_location_atom dw_loc_opc;
@@ -2299,7 +2391,7 @@ dw_loc_descr_node;
/* Location lists are ranges + location descriptions for that range,
so you can track variables that are in different places over
their entire life. */
-typedef struct dw_loc_list_struct
+typedef struct dw_loc_list_struct GTY(())
{
dw_loc_list_ref dw_loc_next;
const char *begin; /* Label for begin address of range */
@@ -2310,6 +2402,8 @@ typedef struct dw_loc_list_struct
dw_loc_descr_ref expr;
} dw_loc_list_node;
+#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
+
static const char *dwarf_stack_op_name PARAMS ((unsigned));
static dw_loc_descr_ref new_loc_descr PARAMS ((enum dwarf_location_atom,
unsigned long,
@@ -2645,10 +2739,8 @@ new_loc_descr (op, oprnd1, oprnd2)
unsigned long oprnd1;
unsigned long oprnd2;
{
- /* Use xcalloc here so we clear out all of the long_long constant in
- the union. */
dw_loc_descr_ref descr
- = (dw_loc_descr_ref) xcalloc (1, sizeof (dw_loc_descr_node));
+ = (dw_loc_descr_ref) ggc_alloc_cleared (sizeof (dw_loc_descr_node));
descr->dw_loc_opc = op;
descr->dw_loc_oprnd1.val_class = dw_val_class_unsigned_const;
@@ -3134,10 +3226,7 @@ get_cfa_from_loc_descr (cfa, loc)
#ifdef DWARF2_DEBUGGING_INFO
/* .debug_str support. */
-static hashnode indirect_string_alloc PARAMS ((hash_table *));
-static int output_indirect_string PARAMS ((struct cpp_reader *,
- hashnode, const PTR));
-
+static int output_indirect_string PARAMS ((void **, void *));
static void dwarf2out_init PARAMS ((const char *));
static void dwarf2out_finish PARAMS ((const char *));
@@ -3179,6 +3268,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
dwarf2out_abstract_function, /* outlining_inline_function */
debug_nothing_rtx /* label */
};
+#endif
/* NOTE: In the comments in this file, many references are made to
"Debugging Information Entries". This term is abbreviated as `DIE'
@@ -3207,7 +3297,7 @@ typedef struct dw_ranges_struct *dw_ranges_ref;
entry. The label gives the PC value associated with
the line number entry. */
-typedef struct dw_line_info_struct
+typedef struct dw_line_info_struct GTY(())
{
unsigned long dw_file_num;
unsigned long dw_line_num;
@@ -3216,7 +3306,7 @@ dw_line_info_entry;
/* Line information for functions in separate sections; each one gets its
own sequence. */
-typedef struct dw_separate_line_info_struct
+typedef struct dw_separate_line_info_struct GTY(())
{
unsigned long dw_file_num;
unsigned long dw_line_num;
@@ -3228,7 +3318,7 @@ dw_separate_line_info_entry;
a link to the next attribute in the chain, and an attribute value.
Attributes are typically linked below the DIE they modify. */
-typedef struct dw_attr_struct
+typedef struct dw_attr_struct GTY(())
{
enum dwarf_attribute dw_attr;
dw_attr_ref dw_attr_next;
@@ -3238,7 +3328,7 @@ dw_attr_node;
/* The Debugging Information Entry (DIE) structure */
-typedef struct die_struct
+typedef struct die_struct GTY(())
{
enum dwarf_tag die_tag;
char *die_symbol;
@@ -3254,20 +3344,20 @@ die_node;
/* The pubname structure */
-typedef struct pubname_struct
+typedef struct pubname_struct GTY(())
{
dw_die_ref die;
char *name;
}
pubname_entry;
-struct dw_ranges_struct
+struct dw_ranges_struct GTY(())
{
int block_num;
};
/* The limbo die list structure. */
-typedef struct limbo_die_struct
+typedef struct limbo_die_struct GTY(())
{
dw_die_ref die;
tree created_for;
@@ -3351,14 +3441,14 @@ limbo_die_node;
static unsigned long next_die_offset;
/* Record the root of the DIE's built for the current compilation unit. */
-static dw_die_ref comp_unit_die;
+static GTY(()) dw_die_ref comp_unit_die;
/* We need special handling in dwarf2out_start_source_file if it is
first one. */
static int is_main_source;
/* A list of DIEs with a NULL parent waiting to be relocated. */
-static limbo_die_node *limbo_die_list = 0;
+static GTY(()) limbo_die_node *limbo_die_list;
/* Structure used by lookup_filename to manage sets of filenames. */
struct file_table
@@ -3379,7 +3469,7 @@ static struct file_table file_table;
/* A pointer to the base of a table of references to DIE's that describe
declarations. The table is indexed by DECL_UID() which is a unique
number identifying each decl. */
-static dw_die_ref *decl_die_table;
+static GTY((length ("decl_die_table_allocated"))) dw_die_ref *decl_die_table;
/* Number of elements currently allocated for the decl_die_table. */
static unsigned decl_die_table_allocated;
@@ -3394,7 +3484,8 @@ static unsigned decl_die_table_in_use;
/* A pointer to the base of a list of references to DIE's that
are uniquely identified by their tag, presence/absence of
children DIE's, and list of attribute/value pairs. */
-static dw_die_ref *abbrev_die_table;
+static GTY((length ("abbrev_die_table_allocated")))
+ dw_die_ref *abbrev_die_table;
/* Number of elements currently allocated for abbrev_die_table. */
static unsigned abbrev_die_table_allocated;
@@ -3408,23 +3499,25 @@ static unsigned abbrev_die_table_in_use;
/* A pointer to the base of a table that contains line information
for each source code line in .text in the compilation unit. */
-static dw_line_info_ref line_info_table;
+static GTY((length ("line_info_table_allocated")))
+ dw_line_info_ref line_info_table;
/* Number of elements currently allocated for line_info_table. */
static unsigned line_info_table_allocated;
-/* Number of elements in separate_line_info_table currently in use. */
-static unsigned separate_line_info_table_in_use;
+/* Number of elements in line_info_table currently in use. */
+static unsigned line_info_table_in_use;
/* A pointer to the base of a table that contains line information
for each source code line outside of .text in the compilation unit. */
-static dw_separate_line_info_ref separate_line_info_table;
+static GTY ((length ("separate_line_info_table_allocated")))
+ dw_separate_line_info_ref separate_line_info_table;
/* Number of elements currently allocated for separate_line_info_table. */
static unsigned separate_line_info_table_allocated;
-/* Number of elements in line_info_table currently in use. */
-static unsigned line_info_table_in_use;
+/* Number of elements in separate_line_info_table currently in use. */
+static unsigned separate_line_info_table_in_use;
/* Size (in elements) of increments by which we may expand the
line_info_table. */
@@ -3432,7 +3525,7 @@ static unsigned line_info_table_in_use;
/* A pointer to the base of a table that contains a list of publicly
accessible names. */
-static pubname_ref pubname_table;
+static GTY ((length ("pubname_table_allocated"))) pubname_ref pubname_table;
/* Number of elements currently allocated for pubname_table. */
static unsigned pubname_table_allocated;
@@ -3445,7 +3538,7 @@ static unsigned pubname_table_in_use;
#define PUBNAME_TABLE_INCREMENT 64
/* Array of dies for which we should generate .debug_arange info. */
-static dw_die_ref *arange_table;
+static GTY((length ("arange_table_allocated"))) dw_die_ref *arange_table;
/* Number of elements currently allocated for arange_table. */
static unsigned arange_table_allocated;
@@ -3458,7 +3551,7 @@ static unsigned arange_table_in_use;
#define ARANGE_TABLE_INCREMENT 64
/* Array of dies for which we should generate .debug_ranges info. */
-static dw_ranges_ref ranges_table;
+static GTY ((length ("ranges_table_allocated"))) dw_ranges_ref ranges_table;
/* Number of elements currently allocated for ranges_table. */
static unsigned ranges_table_allocated;
@@ -3479,6 +3572,8 @@ static int current_function_has_inlines;
static int comp_unit_has_inlines;
#endif
+#ifdef DWARF2_DEBUGGING_INFO
+
/* Forward declarations for functions defined in this file. */
static int is_pseudo_reg PARAMS ((rtx));
@@ -3494,7 +3589,7 @@ static tree decl_ultimate_origin PARAMS ((tree));
static tree block_ultimate_origin PARAMS ((tree));
static tree decl_class_context PARAMS ((tree));
static void add_dwarf_attr PARAMS ((dw_die_ref, dw_attr_ref));
-static inline dw_val_class AT_class PARAMS ((dw_attr_ref));
+static inline enum dw_val_class AT_class PARAMS ((dw_attr_ref));
static void add_AT_flag PARAMS ((dw_die_ref,
enum dwarf_attribute,
unsigned));
@@ -3513,6 +3608,8 @@ static void add_AT_long_long PARAMS ((dw_die_ref,
static void add_AT_float PARAMS ((dw_die_ref,
enum dwarf_attribute,
unsigned, long *));
+static hashval_t debug_str_do_hash PARAMS ((const void *));
+static int debug_str_eq PARAMS ((const void *, const void *));
static void add_AT_string PARAMS ((dw_die_ref,
enum dwarf_attribute,
const char *));
@@ -3737,7 +3834,6 @@ static void add_loc_descr_to_loc_list PARAMS ((dw_loc_list_ref *,
const char *, const char *, const char *));
static void output_loc_list PARAMS ((dw_loc_list_ref));
static char *gen_internal_sym PARAMS ((const char *));
-static void mark_limbo_die_list PARAMS ((void *));
/* Section names used to hold DWARF debugging information. */
#ifndef DEBUG_INFO_SECTION
@@ -4404,7 +4500,7 @@ add_dwarf_attr (die, attr)
}
}
-static inline dw_val_class
+static inline enum dw_val_class
AT_class (a)
dw_attr_ref a;
{
@@ -4419,7 +4515,7 @@ add_AT_flag (die, attr_kind, flag)
enum dwarf_attribute attr_kind;
unsigned flag;
{
- dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
@@ -4446,7 +4542,7 @@ add_AT_int (die, attr_kind, int_val)
enum dwarf_attribute attr_kind;
long int int_val;
{
- dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
@@ -4473,7 +4569,7 @@ add_AT_unsigned (die, attr_kind, unsigned_val)
enum dwarf_attribute attr_kind;
unsigned long unsigned_val;
{
- dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
@@ -4501,7 +4597,7 @@ add_AT_long_long (die, attr_kind, val_hi, val_low)
unsigned long val_hi;
unsigned long val_low;
{
- dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
@@ -4520,7 +4616,7 @@ add_AT_float (die, attr_kind, length, array)
unsigned length;
long *array;
{
- dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
@@ -4530,6 +4626,24 @@ add_AT_float (die, attr_kind, length, array)
add_dwarf_attr (die, attr);
}
+/* Hash and equality functions for debug_str_hash. */
+
+static hashval_t
+debug_str_do_hash (x)
+ const void * x;
+{
+ return htab_hash_string (((const struct indirect_string_node *)x)->str);
+}
+
+static int
+debug_str_eq (x1, x2)
+ const void * x1;
+ const void * x2;
+{
+ return strcmp ((((const struct indirect_string_node *)x1)->str),
+ (const char *)x2) == 0;
+}
+
/* Add a string attribute value to a DIE. */
static inline void
@@ -4538,18 +4652,20 @@ add_AT_string (die, attr_kind, str)
enum dwarf_attribute attr_kind;
const char *str;
{
- dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
struct indirect_string_node *node;
+ PTR *slot;
if (! debug_str_hash)
- {
- debug_str_hash = ht_create (10);
- debug_str_hash->alloc_node = indirect_string_alloc;
- }
-
- node = (struct indirect_string_node *)
- ht_lookup (debug_str_hash, (const unsigned char *) str,
- strlen (str), HT_ALLOC);
+ debug_str_hash = htab_create_ggc (10, debug_str_do_hash,
+ debug_str_eq, NULL);
+
+ slot = htab_find_slot_with_hash (debug_str_hash, str,
+ htab_hash_string (str), INSERT);
+ if (*slot == NULL)
+ *slot = ggc_alloc_cleared (sizeof (struct indirect_string_node));
+ node = (struct indirect_string_node *) *slot;
+ node->str = ggc_alloc_string (str, -1);
node->refcount++;
attr->dw_attr_next = NULL;
@@ -4564,7 +4680,7 @@ AT_string (a)
dw_attr_ref a;
{
if (a && AT_class (a) == dw_val_class_str)
- return (const char *) HT_STR (&a->dw_attr_val.v.val_str->id);
+ return a->dw_attr_val.v.val_str->str;
abort ();
}
@@ -4580,14 +4696,13 @@ AT_string_form (a)
{
struct indirect_string_node *node;
unsigned int len;
- extern int const_labelno;
char label[32];
node = a->dw_attr_val.v.val_str;
if (node->form)
return node->form;
- len = HT_LEN (&node->id) + 1;
+ len = strlen (node->str) + 1;
/* If the string is shorter or equal to the size of the reference, it is
always better to put it inline. */
@@ -4601,8 +4716,8 @@ AT_string_form (a)
&& (len - DWARF_OFFSET_SIZE) * node->refcount <= len)
return node->form = DW_FORM_string;
- ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno);
- ++const_labelno;
+ ASM_GENERATE_INTERNAL_LABEL (label, "LASF", dw2_string_counter);
+ ++dw2_string_counter;
node->label = xstrdup (label);
return node->form = DW_FORM_strp;
@@ -4619,7 +4734,7 @@ add_AT_die_ref (die, attr_kind, targ_die)
enum dwarf_attribute attr_kind;
dw_die_ref targ_die;
{
- dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
@@ -4668,7 +4783,7 @@ add_AT_fde_ref (die, attr_kind, targ_fde)
enum dwarf_attribute attr_kind;
unsigned targ_fde;
{
- dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
@@ -4685,7 +4800,7 @@ add_AT_loc (die, attr_kind, loc)
enum dwarf_attribute attr_kind;
dw_loc_descr_ref loc;
{
- dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
@@ -4710,7 +4825,7 @@ add_AT_loc_list (die, attr_kind, loc_list)
enum dwarf_attribute attr_kind;
dw_loc_list_ref loc_list;
{
- dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
@@ -4738,7 +4853,7 @@ add_AT_addr (die, attr_kind, addr)
enum dwarf_attribute attr_kind;
rtx addr;
{
- dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
@@ -4765,7 +4880,7 @@ add_AT_lbl_id (die, attr_kind, lbl_id)
enum dwarf_attribute attr_kind;
const char *lbl_id;
{
- dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
@@ -4782,7 +4897,7 @@ add_AT_lbl_offset (die, attr_kind, label)
enum dwarf_attribute attr_kind;
const char *label;
{
- dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
@@ -4799,7 +4914,7 @@ add_AT_offset (die, attr_kind, offset)
enum dwarf_attribute attr_kind;
unsigned long offset;
{
- dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
@@ -4816,7 +4931,7 @@ add_AT_range_list (die, attr_kind, offset)
enum dwarf_attribute attr_kind;
unsigned long offset;
{
- dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
@@ -4976,27 +5091,9 @@ static inline void
free_AT (a)
dw_attr_ref a;
{
- switch (AT_class (a))
- {
- case dw_val_class_str:
- if (a->dw_attr_val.v.val_str->refcount)
- a->dw_attr_val.v.val_str->refcount--;
- break;
-
- case dw_val_class_lbl_id:
- case dw_val_class_lbl_offset:
- free (a->dw_attr_val.v.val_lbl_id);
- break;
-
- case dw_val_class_float:
- free (a->dw_attr_val.v.val_float.array);
- break;
-
- default:
- break;
- }
-
- free (a);
+ if (AT_class (a) == dw_val_class_str)
+ if (a->dw_attr_val.v.val_str->refcount)
+ a->dw_attr_val.v.val_str->refcount--;
}
/* Remove the specified attribute if present. */
@@ -5031,7 +5128,6 @@ free_die (die)
dw_die_ref die;
{
remove_children (die);
- free (die);
}
/* Discard the children of this DIE. */
@@ -5124,7 +5220,7 @@ new_die (tag_value, parent_die, t)
dw_die_ref parent_die;
tree t;
{
- dw_die_ref die = (dw_die_ref) xcalloc (1, sizeof (die_node));
+ dw_die_ref die = (dw_die_ref) ggc_alloc_cleared (sizeof (die_node));
die->die_tag = tag_value;
@@ -5134,7 +5230,7 @@ new_die (tag_value, parent_die, t)
{
limbo_die_node *limbo_node;
- limbo_node = (limbo_die_node *) xmalloc (sizeof (limbo_die_node));
+ limbo_node = ggc_alloc_cleared (sizeof (limbo_die_node));
limbo_node->die = die;
limbo_node->created_for = t;
limbo_node->next = limbo_die_list;
@@ -5191,9 +5287,8 @@ equate_decl_number_to_die (decl, decl_die)
/ DECL_DIE_TABLE_INCREMENT)
* DECL_DIE_TABLE_INCREMENT;
- decl_die_table
- = (dw_die_ref *) xrealloc (decl_die_table,
- sizeof (dw_die_ref) * num_allocated);
+ decl_die_table = ggc_realloc (decl_die_table,
+ sizeof (dw_die_ref) * num_allocated);
memset ((char *) &decl_die_table[decl_die_table_allocated], 0,
(num_allocated - decl_die_table_allocated) * sizeof (dw_die_ref));
@@ -5605,8 +5700,7 @@ same_dw_val_p (v1, v2, mark)
case dw_val_class_flag:
return v1->v.val_flag == v2->v.val_flag;
case dw_val_class_str:
- return !strcmp((const char *) HT_STR (&v1->v.val_str->id),
- (const char *) HT_STR (&v2->v.val_str->id));
+ return !strcmp(v1->v.val_str->str, v2->v.val_str->str);
case dw_val_class_addr:
r1 = v1->v.val_addr;
@@ -6145,9 +6239,8 @@ build_abbrev_table (die)
if (abbrev_die_table_in_use >= abbrev_die_table_allocated)
{
n_alloc = abbrev_die_table_allocated + ABBREV_DIE_TABLE_INCREMENT;
- abbrev_die_table
- = (dw_die_ref *) xrealloc (abbrev_die_table,
- sizeof (dw_die_ref) * n_alloc);
+ abbrev_die_table = ggc_realloc (abbrev_die_table,
+ sizeof (dw_die_ref) * n_alloc);
memset ((char *) &abbrev_die_table[abbrev_die_table_allocated], 0,
(n_alloc - abbrev_die_table_allocated) * sizeof (dw_die_ref));
@@ -6249,7 +6342,7 @@ size_of_die (die)
if (AT_string_form (a) == DW_FORM_strp)
size += DWARF_OFFSET_SIZE;
else
- size += HT_LEN (&a->dw_attr_val.v.val_str->id) + 1;
+ size += strlen (a->dw_attr_val.v.val_str->str) + 1;
break;
default:
abort ();
@@ -6529,8 +6622,7 @@ new_loc_list (expr, begin, end, section, gensym)
const char *section;
unsigned gensym;
{
- dw_loc_list_ref retlist
- = (dw_loc_list_ref) xcalloc (1, sizeof (dw_loc_list_node));
+ dw_loc_list_ref retlist = ggc_alloc_cleared (sizeof (dw_loc_list_node));
retlist->begin = begin;
retlist->end = end;
@@ -6884,9 +6976,11 @@ add_pubname (decl, die)
{
pubname_table_allocated += PUBNAME_TABLE_INCREMENT;
pubname_table
- = (pubname_ref) xrealloc (pubname_table,
- (pubname_table_allocated
- * sizeof (pubname_entry)));
+ = (pubname_ref) ggc_realloc (pubname_table,
+ (pubname_table_allocated
+ * sizeof (pubname_entry)));
+ memset (pubname_table + pubname_table_in_use, 0,
+ PUBNAME_TABLE_INCREMENT * sizeof (pubname_entry));
}
p = &pubname_table[pubname_table_in_use++];
@@ -6942,8 +7036,11 @@ add_arange (decl, die)
if (arange_table_in_use == arange_table_allocated)
{
arange_table_allocated += ARANGE_TABLE_INCREMENT;
- arange_table = (dw_die_ref *)
- xrealloc (arange_table, arange_table_allocated * sizeof (dw_die_ref));
+ arange_table = ggc_realloc (arange_table,
+ (arange_table_allocated
+ * sizeof (dw_die_ref)));
+ memset (arange_table + arange_table_in_use, 0,
+ ARANGE_TABLE_INCREMENT * sizeof (dw_die_ref));
}
arange_table[arange_table_in_use++] = die;
@@ -7038,8 +7135,10 @@ add_ranges (block)
{
ranges_table_allocated += RANGES_TABLE_INCREMENT;
ranges_table = (dw_ranges_ref)
- xrealloc (ranges_table, (ranges_table_allocated
- * sizeof (struct dw_ranges_struct)));
+ ggc_realloc (ranges_table, (ranges_table_allocated
+ * sizeof (struct dw_ranges_struct)));
+ memset (ranges_table + ranges_table_in_use, 0,
+ RANGES_TABLE_INCREMENT * sizeof (struct dw_ranges_struct));
}
ranges_table[in_use].block_num = (block ? BLOCK_NUMBER (block) : 0);
@@ -9090,7 +9189,7 @@ add_const_value_attribute (die, rtl)
if (GET_MODE_CLASS (mode) == MODE_FLOAT)
{
unsigned length = GET_MODE_SIZE (mode) / 4;
- long *array = (long *) xmalloc (sizeof (long) * length);
+ long *array = (long *) ggc_alloc (sizeof (long) * length);
REAL_VALUE_TYPE rv;
REAL_VALUE_FROM_CONST_DOUBLE (rv, rtl);
@@ -11974,15 +12073,6 @@ gen_decl_die (decl, context_die)
abort ();
}
}
-
-static void
-mark_limbo_die_list (ptr)
- void *ptr ATTRIBUTE_UNUSED;
-{
- limbo_die_node *node;
- for (node = limbo_die_list; node; node = node->next)
- ggc_mark_tree (node->created_for);
-}
/* Add Ada "use" clause information for SGI Workshop debugger. */
@@ -12225,6 +12315,8 @@ lookup_filename (file_name)
file_table.allocated = i + FILE_TABLE_INCREMENT;
file_table.table = (char **)
xrealloc (file_table.table, file_table.allocated * sizeof (char *));
+ memset (file_table.table + i, 0,
+ FILE_TABLE_INCREMENT * sizeof (char *));
}
/* Add the new entry to the end of the filename table. */
@@ -12299,9 +12391,14 @@ dwarf2out_source_line (line, filename)
separate_line_info_table_allocated += LINE_INFO_TABLE_INCREMENT;
separate_line_info_table
= (dw_separate_line_info_ref)
- xrealloc (separate_line_info_table,
- separate_line_info_table_allocated
- * sizeof (dw_separate_line_info_entry));
+ ggc_realloc (separate_line_info_table,
+ separate_line_info_table_allocated
+ * sizeof (dw_separate_line_info_entry));
+ memset ((separate_line_info_table
+ + separate_line_info_table_in_use),
+ 0,
+ (LINE_INFO_TABLE_INCREMENT
+ * sizeof (dw_separate_line_info_entry)));
}
/* Add the new entry at the end of the line_info_table. */
@@ -12323,10 +12420,11 @@ dwarf2out_source_line (line, filename)
{
line_info_table_allocated += LINE_INFO_TABLE_INCREMENT;
line_info_table
- = (dw_line_info_ref)
- xrealloc (line_info_table,
- (line_info_table_allocated
- * sizeof (dw_line_info_entry)));
+ = ggc_realloc (line_info_table,
+ (line_info_table_allocated
+ * sizeof (dw_line_info_entry)));
+ memset (line_info_table + line_info_table_in_use, 0,
+ LINE_INFO_TABLE_INCREMENT * sizeof (dw_line_info_entry));
}
/* Add the new entry at the end of the line_info_table. */
@@ -12433,8 +12531,8 @@ dwarf2out_init (main_input_filename)
lookup_filename (main_input_filename);
/* Allocate the initial hunk of the decl_die_table. */
- decl_die_table
- = (dw_die_ref *) xcalloc (DECL_DIE_TABLE_INCREMENT, sizeof (dw_die_ref));
+ decl_die_table = ggc_alloc_cleared (DECL_DIE_TABLE_INCREMENT
+ * sizeof (dw_die_ref));
decl_die_table_allocated = DECL_DIE_TABLE_INCREMENT;
decl_die_table_in_use = 0;
@@ -12442,17 +12540,15 @@ dwarf2out_init (main_input_filename)
VARRAY_TREE_INIT (decl_scope_table, 256, "decl_scope_table");
/* Allocate the initial hunk of the abbrev_die_table. */
- abbrev_die_table
- = (dw_die_ref *) xcalloc (ABBREV_DIE_TABLE_INCREMENT,
- sizeof (dw_die_ref));
+ abbrev_die_table = ggc_alloc_cleared (ABBREV_DIE_TABLE_INCREMENT
+ * sizeof (dw_die_ref));
abbrev_die_table_allocated = ABBREV_DIE_TABLE_INCREMENT;
/* Zero-th entry is allocated, but unused */
abbrev_die_table_in_use = 1;
/* Allocate the initial hunk of the line_info_table. */
- line_info_table
- = (dw_line_info_ref) xcalloc (LINE_INFO_TABLE_INCREMENT,
- sizeof (dw_line_info_entry));
+ line_info_table = ggc_alloc_cleared (LINE_INFO_TABLE_INCREMENT
+ * sizeof (dw_line_info_entry));
line_info_table_allocated = LINE_INFO_TABLE_INCREMENT;
/* Zero-th entry is allocated, but unused */
@@ -12470,8 +12566,6 @@ dwarf2out_init (main_input_filename)
VARRAY_RTX_INIT (used_rtx_varray, 32, "used_rtx_varray");
- ggc_add_root (&limbo_die_list, 1, 1, mark_limbo_die_list);
-
ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label,
DEBUG_ABBREV_SECTION_LABEL, 0);
@@ -12508,39 +12602,21 @@ dwarf2out_init (main_input_filename)
}
}
-/* Allocate a string in .debug_str hash table. */
-
-static hashnode
-indirect_string_alloc (tab)
- hash_table *tab ATTRIBUTE_UNUSED;
-{
- struct indirect_string_node *node;
-
- node = xmalloc (sizeof (struct indirect_string_node));
- node->refcount = 0;
- node->form = 0;
- node->label = NULL;
-
- return (hashnode) node;
-}
-
/* A helper function for dwarf2out_finish called through
ht_forall. Emit one queued .debug_str string. */
static int
-output_indirect_string (pfile, h, v)
- struct cpp_reader *pfile ATTRIBUTE_UNUSED;
- hashnode h;
- const PTR v ATTRIBUTE_UNUSED;
+output_indirect_string (h, v)
+ void **h;
+ void *v ATTRIBUTE_UNUSED;
{
- struct indirect_string_node *node = (struct indirect_string_node *) h;
+ struct indirect_string_node *node = (struct indirect_string_node *) *h;
if (node->form == DW_FORM_strp)
{
named_section_flags (DEBUG_STR_SECTION, DEBUG_STR_SECTION_FLAGS);
ASM_OUTPUT_LABEL (asm_out_file, node->label);
- assemble_string ((const char *) HT_STR (&node->id),
- HT_LEN (&node->id) + 1);
+ assemble_string (node->str, strlen (node->str) + 1);
}
return 1;
@@ -12607,8 +12683,6 @@ dwarf2out_finish (input_filename)
else
abort ();
}
-
- free (node);
}
limbo_die_list = NULL;
@@ -12724,7 +12798,7 @@ dwarf2out_finish (input_filename)
/* If we emitted any DW_FORM_strp form attribute, output the string
table too. */
if (debug_str_hash)
- ht_forall (debug_str_hash, output_indirect_string, NULL);
+ htab_traverse (debug_str_hash, output_indirect_string, NULL);
}
#else
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 0099a50ee3c..eb1814acc78 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -5315,14 +5315,14 @@ init_emit_once (line_numbers)
/* Initialize the CONST_INT, CONST_DOUBLE, and memory attribute hash
tables. */
- const_int_htab = htab_create (37, const_int_htab_hash,
- const_int_htab_eq, NULL);
+ const_int_htab = htab_create_ggc (37, const_int_htab_hash,
+ const_int_htab_eq, NULL);
- const_double_htab = htab_create (37, const_double_htab_hash,
- const_double_htab_eq, NULL);
+ const_double_htab = htab_create_ggc (37, const_double_htab_hash,
+ const_double_htab_eq, NULL);
- mem_attrs_htab = htab_create (37, mem_attrs_htab_hash,
- mem_attrs_htab_eq, NULL);
+ mem_attrs_htab = htab_create_ggc (37, mem_attrs_htab_hash,
+ mem_attrs_htab_eq, NULL);
no_line_numbers = ! line_numbers;
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 0c53604e7d5..3847fc00041 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -1395,7 +1395,7 @@ size_int_type_wide (number, type)
if (size_htab == 0)
{
- size_htab = htab_create (1024, size_htab_hash, size_htab_eq, NULL);
+ size_htab = htab_create_ggc (1024, size_htab_hash, size_htab_eq, NULL);
new_const = make_node (INTEGER_CST);
}
diff --git a/gcc/function.c b/gcc/function.c
index 0a0f56d2375..1c972d2cff4 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -125,7 +125,7 @@ int current_function_uses_only_leaf_regs;
int virtuals_instantiated;
/* Assign unique numbers to labels generated for profiling, debugging, etc. */
-static int funcdef_no;
+static GTY(()) int funcdef_no;
/* These variables hold pointers to functions to create and destroy
target specific, per-function data structures. */
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 618d2723208..8b27a0ac579 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -421,6 +421,7 @@ or with constant text in a single argument.
%w marks the argument containing or following the %w as the
"output file" of this compilation. This puts the argument
into the sequence of arguments that %o will substitute later.
+ %V indicates that this compilation produces no "output file".
%W{...}
like %{...} but mark last argument supplied within
as a file to be deleted on failure.
@@ -914,9 +915,19 @@ static const struct compiler default_compilers[] =
%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)", 0},
{".h", "@c-header", 0},
{"@c-header",
- "%{!E:%ecompilation of header file requested} \
- %(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)",
- 0},
+ /* cc1 has an integrated ISO C preprocessor. We should invoke the
+ external preprocessor if -save-temps is given. */
+ "%{E|M|MM:%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)}\
+ %{!E:%{!M:%{!MM:\
+ %{save-temps|traditional-cpp:%(trad_capable_cpp) \
+ %(cpp_options) %b.i \n\
+ cc1 -fpreprocessed %b.i %(cc1_options)\
+ -o %g.s %{!o*:--output-pch=%i.pch}\
+ %W{o*:--output-pch=%*}%V}\
+ %{!save-temps:%{!traditional-cpp:\
+ cc1 %(cpp_unique_options) %(cc1_options)\
+ -o %g.s %{!o*:--output-pch=%i.pch}\
+ %W{o*:--output-pch=%*}%V}}}}}", 0},
{".i", "@cpp-output", 0},
{"@cpp-output",
"%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}", 0},
@@ -4765,6 +4776,10 @@ do_spec_1 (spec, inswitch, soft_matched_part)
this_is_library_file = 1;
break;
+ case 'V':
+ outfiles[input_file_number] = NULL;
+ break;
+
case 'w':
this_is_output_file = 1;
break;
@@ -6079,6 +6094,7 @@ main (argc, argv)
size_t i;
int value;
int linker_was_run = 0;
+ int num_linker_inputs = 0;
char *explicit_link_files;
char *specs_file;
const char *p;
@@ -6516,9 +6532,15 @@ main (argc, argv)
error_count++;
}
+ /* Determine if there are any linker input files. */
+ num_linker_inputs = 0;
+ for (i = 0; (int) i < n_infiles; i++)
+ if (explicit_link_files[i] || outfiles[i] != NULL)
+ num_linker_inputs++;
+
/* Run ld to link all the compiler output files. */
- if (error_count == 0)
+ if (num_linker_inputs > 0 && error_count == 0)
{
int tmp = execution_count;
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index 855e5edfe96..b279263b548 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -603,14 +603,6 @@ adjust_field_rtx_def (t, opt)
subfields->opt->name = "skip";
subfields->opt->info = NULL;
}
- else if ((size_t) rtx_next[i] == aindex)
- {
- /* The 'next' field will be marked by the chain_next option. */
- subfields->opt = xmalloc (sizeof (*subfields->opt));
- subfields->opt->next = nodot;
- subfields->opt->name = "skip";
- subfields->opt->info = NULL;
- }
else
subfields->opt = nodot;
}
@@ -1364,70 +1356,78 @@ struct flist {
outf_p f;
};
-static void output_escaped_param PARAMS ((outf_p , const char *, const char *,
- const char *, const char *,
- struct fileloc *));
+struct walk_type_data;
+
+/* For scalars and strings, given the item in 'val'.
+ For structures, given a pointer to the item in 'val'.
+ For misc. pointers, given the item in 'val'.
+*/
+typedef void (*process_field_fn)
+ PARAMS ((type_p f, const struct walk_type_data *p));
+typedef void (*func_name_fn)
+ PARAMS ((type_p s, const struct walk_type_data *p));
+
+/* Parameters for write_types. */
+
+struct write_types_data
+{
+ const char *prefix;
+ const char *param_prefix;
+ const char *subfield_marker_routine;
+ const char *marker_routine;
+ const char *reorder_note_routine;
+ const char *comment;
+};
+
+static void output_escaped_param PARAMS ((struct walk_type_data *d,
+ const char *, const char *));
static void output_mangled_typename PARAMS ((outf_p, type_p));
-static void write_gc_structure_fields
- PARAMS ((outf_p , type_p, const char *, const char *, options_p,
- int, struct fileloc *, lang_bitmap, type_p *));
-static void write_gc_marker_routine_for_structure PARAMS ((type_p, type_p,
- type_p *));
-static void write_gc_types PARAMS ((type_p structures, type_p param_structs));
+static void walk_type PARAMS ((type_p t, struct walk_type_data *d));
+static void write_func_for_structure
+ PARAMS ((type_p orig_s, type_p s, type_p * param,
+ const struct write_types_data *wtd));
+static void write_types_process_field
+ PARAMS ((type_p f, const struct walk_type_data *d));
+static void write_types PARAMS ((type_p structures,
+ type_p param_structs,
+ const struct write_types_data *wtd));
+static void write_types_local_process_field
+ PARAMS ((type_p f, const struct walk_type_data *d));
+static void write_local_func_for_structure
+ PARAMS ((type_p orig_s, type_p s, type_p * param));
+static void write_local PARAMS ((type_p structures,
+ type_p param_structs));
static void write_enum_defn PARAMS ((type_p structures, type_p param_structs));
+static int contains_scalar_p PARAMS ((type_p t));
static void put_mangled_filename PARAMS ((outf_p , const char *));
static void finish_root_table PARAMS ((struct flist *flp, const char *pfx,
const char *tname, const char *lastname,
const char *name));
-static void write_gc_root PARAMS ((outf_p , pair_p, type_p, const char *, int,
+static void write_root PARAMS ((outf_p , pair_p, type_p, const char *, int,
struct fileloc *, const char *));
-static void write_gc_roots PARAMS ((pair_p));
+static void write_array PARAMS ((outf_p f, pair_p v,
+ const struct write_types_data *wtd));
+static void write_roots PARAMS ((pair_p));
-static int gc_counter;
+/* Parameters for walk_type. */
-/* Print PARAM to OF processing escapes. VAL references the current object,
- PREV_VAL the object containing the current object, ONAME is the name
- of the option and LINE is used to print error messages. */
-
-static void
-output_escaped_param (of, param, val, prev_val, oname, line)
- outf_p of;
- const char *param;
- const char *val;
- const char *prev_val;
- const char *oname;
- struct fileloc *line;
+struct walk_type_data
{
- const char *p;
-
- for (p = param; *p; p++)
- if (*p != '%')
- oprintf (of, "%c", *p);
- else switch (*++p)
- {
- case 'h':
- oprintf (of, "(%s)", val);
- break;
- case '0':
- oprintf (of, "(*x)");
- break;
- case '1':
- oprintf (of, "(%s)", prev_val);
- break;
- case 'a':
- {
- const char *pp = val + strlen (val);
- while (pp[-1] == ']')
- while (*pp != '[')
- pp--;
- oprintf (of, "%s", pp);
- }
- break;
- default:
- error_at_line (line, "`%s' option contains bad escape %c%c",
- oname, '%', *p);
- }
-}
+ process_field_fn process_field;
+ const void *cookie;
+ outf_p of;
+ options_p opt;
+ const char *val;
+ const char *prev_val[4];
+ int indent;
+ int counter;
+ struct fileloc *line;
+ lang_bitmap bitmap;
+ type_p *param;
+ int used_length;
+ type_p orig_s;
+ const char *reorder_fn;
+};
/* Print a mangled name representing T to OF. */
@@ -1469,423 +1469,491 @@ output_mangled_typename (of, t)
}
}
-/* Write out code to OF which marks the fields of S. VAL references
- the current object, PREV_VAL the object containing the current
- object, OPTS is a list of options to apply, INDENT is the current
- indentation level, LINE is used to print error messages, BITMAP
- indicates which languages to print the structure for, and PARAM is
- the current parameter (from an enclosing param_is option). */
+/* Print PARAM to D->OF processing escapes. D->VAL references the
+ current object, D->PREV_VAL the object containing the current
+ object, ONAME is the name of the option and D->LINE is used to
+ print error messages. */
static void
-write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap,
- param)
- outf_p of;
- type_p s;
- const char *val;
- const char *prev_val;
- options_p opts;
- int indent;
- struct fileloc *line;
- lang_bitmap bitmap;
- type_p * param;
+output_escaped_param (d, param, oname)
+ struct walk_type_data *d;
+ const char *param;
+ const char *oname;
{
- pair_p f;
- int seen_default = 0;
-
- if (! s->u.s.line.file)
- error_at_line (line, "incomplete structure `%s'", s->u.s.tag);
- else if ((s->u.s.bitmap & bitmap) != bitmap)
- {
- error_at_line (line, "structure defined for mismatching languages");
- error_at_line (&s->u.s.line, "one structure defined here");
- }
+ const char *p;
- if (s->kind == TYPE_UNION)
- {
- const char *tagexpr = NULL;
- options_p oo;
-
- for (oo = opts; oo; oo = oo->next)
- if (strcmp (oo->name, "desc") == 0)
- tagexpr = (const char *)oo->info;
- if (tagexpr == NULL)
+ for (p = param; *p; p++)
+ if (*p != '%')
+ oprintf (d->of, "%c", *p);
+ else switch (*++p)
+ {
+ case 'h':
+ oprintf (d->of, "(%s)", d->prev_val[2]);
+ break;
+ case '0':
+ oprintf (d->of, "(%s)", d->prev_val[0]);
+ break;
+ case '1':
+ oprintf (d->of, "(%s)", d->prev_val[1]);
+ break;
+ case 'a':
{
- tagexpr = "1";
- error_at_line (line, "missing `desc' option");
+ const char *pp = d->val + strlen (d->val);
+ while (pp[-1] == ']')
+ while (*pp != '[')
+ pp--;
+ oprintf (d->of, "%s", pp);
}
+ break;
+ default:
+ error_at_line (d->line, "`%s' option contains bad escape %c%c",
+ oname, '%', *p);
+ }
+}
- oprintf (of, "%*sswitch (", indent, "");
- output_escaped_param (of, tagexpr, val, prev_val, "desc", line);
- oprintf (of, ")\n");
- indent += 2;
- oprintf (of, "%*s{\n", indent, "");
- }
-
- for (f = s->u.s.fields; f; f = f->next)
- {
- const char *tagid = NULL;
- const char *length = NULL;
- int skip_p = 0;
- int default_p = 0;
- int maybe_undef_p = 0;
- int use_param_num = -1;
- int use_params_p = 0;
- int needs_cast_p = 0;
- options_p oo;
- type_p t = f->type;
- const char *dot = ".";
-
- for (oo = f->opt; oo; oo = oo->next)
- if (strcmp (oo->name, "length") == 0)
- length = (const char *)oo->info;
- else if (strcmp (oo->name, "maybe_undef") == 0)
- maybe_undef_p = 1;
- else if (strcmp (oo->name, "tag") == 0)
- tagid = (const char *)oo->info;
- else if (strcmp (oo->name, "special") == 0)
- ;
- else if (strcmp (oo->name, "skip") == 0)
- skip_p = 1;
- else if (strcmp (oo->name, "default") == 0)
- default_p = 1;
- else if (strcmp (oo->name, "desc") == 0)
- ;
- else if (strcmp (oo->name, "descbits") == 0)
- ;
- else if (strcmp (oo->name, "param_is") == 0)
- ;
- else if (strncmp (oo->name, "use_param", 9) == 0
- && (oo->name[9] == '\0' || ISDIGIT (oo->name[9])))
- use_param_num = oo->name[9] == '\0' ? 0 : oo->name[9] - '0';
- else if (strcmp (oo->name, "use_params") == 0)
- use_params_p = 1;
- else if (strcmp (oo->name, "dot") == 0)
- dot = (const char *)oo->info;
- else
- error_at_line (&f->line, "unknown field option `%s'\n", oo->name);
+/* Call D->PROCESS_FIELD for every field (or subfield) of D->VAL,
+ which is of type T. Write code to D->OF to constrain execution (at
+ the point that D->PROCESS_FIELD is called) to the appropriate
+ cases. D->PREV_VAL lists the objects containing the current object,
+ D->OPT is a list of options to apply, D->INDENT is the current
+ indentation level, D->LINE is used to print error messages,
+ D->BITMAP indicates which languages to print the structure for, and
+ D->PARAM is the current parameter (from an enclosing param_is
+ option). */
- if (skip_p)
- continue;
+static void
+walk_type (t, d)
+ type_p t;
+ struct walk_type_data *d;
+{
+ const char *length = NULL;
+ const char *desc = NULL;
+ int maybe_undef_p = 0;
+ int use_param_num = -1;
+ int use_params_p = 0;
+ int needs_cast_p = 0;
+ options_p oo;
+
+ for (oo = d->opt; oo; oo = oo->next)
+ if (strcmp (oo->name, "length") == 0)
+ length = (const char *)oo->info;
+ else if (strcmp (oo->name, "maybe_undef") == 0)
+ maybe_undef_p = 1;
+ else if (strncmp (oo->name, "use_param", 9) == 0
+ && (oo->name[9] == '\0' || ISDIGIT (oo->name[9])))
+ use_param_num = oo->name[9] == '\0' ? 0 : oo->name[9] - '0';
+ else if (strcmp (oo->name, "use_params") == 0)
+ use_params_p = 1;
+ else if (strcmp (oo->name, "desc") == 0)
+ desc = (const char *)oo->info;
+ else if (strcmp (oo->name, "dot") == 0)
+ ;
+ else if (strcmp (oo->name, "tag") == 0)
+ ;
+ else if (strcmp (oo->name, "special") == 0)
+ ;
+ else if (strcmp (oo->name, "skip") == 0)
+ ;
+ else if (strcmp (oo->name, "default") == 0)
+ ;
+ else if (strcmp (oo->name, "descbits") == 0)
+ ;
+ else if (strcmp (oo->name, "param_is") == 0)
+ ;
+ else if (strcmp (oo->name, "chain_next") == 0)
+ ;
+ else if (strcmp (oo->name, "chain_prev") == 0)
+ ;
+ else if (strcmp (oo->name, "reorder") == 0)
+ ;
+ else
+ error_at_line (d->line, "unknown option `%s'\n", oo->name);
- if (use_params_p)
- {
- int pointer_p = t->kind == TYPE_POINTER;
+ if (d->used_length)
+ length = NULL;
- if (pointer_p)
- t = t->u.p;
- t = find_param_structure (t, param);
- if (pointer_p)
- t = create_pointer (t);
- }
+ if (use_params_p)
+ {
+ int pointer_p = t->kind == TYPE_POINTER;
- if (use_param_num != -1)
- {
- if (param != NULL && param[use_param_num] != NULL)
- {
- type_p nt = param[use_param_num];
-
- if (t->kind == TYPE_ARRAY)
- nt = create_array (nt, t->u.a.len);
- else if (length != NULL && t->kind == TYPE_POINTER)
- nt = create_pointer (nt);
- needs_cast_p = (t->kind != TYPE_POINTER
- && nt->kind == TYPE_POINTER);
- t = nt;
- }
- else if (s->kind != TYPE_UNION)
- error_at_line (&f->line, "no parameter defined");
- }
-
- if (t->kind == TYPE_SCALAR
- || (t->kind == TYPE_ARRAY
- && t->u.a.p->kind == TYPE_SCALAR))
- continue;
+ if (pointer_p)
+ t = t->u.p;
+ if (! UNION_OR_STRUCT_P (t))
+ error_at_line (d->line, "`use_params' option on unimplemented type");
+ else
+ t = find_param_structure (t, d->param);
+ if (pointer_p)
+ t = create_pointer (t);
+ }
- seen_default |= default_p;
-
- if (maybe_undef_p
- && (t->kind != TYPE_POINTER
- || t->u.p->kind != TYPE_STRUCT))
- error_at_line (&f->line,
- "field `%s' has invalid option `maybe_undef_p'\n",
- f->name);
- if (s->kind == TYPE_UNION)
+ if (use_param_num != -1)
+ {
+ if (d->param != NULL && d->param[use_param_num] != NULL)
{
- if (tagid)
- {
- oprintf (of, "%*scase %s:\n", indent, "", tagid);
-
- }
- else if (default_p)
- {
- oprintf (of, "%*sdefault:\n", indent, "");
- }
- else
- {
- error_at_line (&f->line, "field `%s' has no tag", f->name);
- continue;
- }
- indent += 2;
+ type_p nt = d->param[use_param_num];
+
+ if (t->kind == TYPE_ARRAY)
+ nt = create_array (nt, t->u.a.len);
+ else if (length != NULL && t->kind == TYPE_POINTER)
+ nt = create_pointer (nt);
+ needs_cast_p = (t->kind != TYPE_POINTER
+ && nt->kind == TYPE_POINTER);
+ t = nt;
}
+ else
+ error_at_line (d->line, "no parameter defined for `%s'",
+ d->val);
+ }
+
+ if (maybe_undef_p
+ && (t->kind != TYPE_POINTER || ! UNION_OR_STRUCT_P (t->u.p)))
+ {
+ error_at_line (d->line,
+ "field `%s' has invalid option `maybe_undef_p'\n",
+ d->val);
+ return;
+ }
+
+ switch (t->kind)
+ {
+ case TYPE_SCALAR:
+ case TYPE_STRING:
+ d->process_field (t, d);
+ break;
- switch (t->kind)
- {
- case TYPE_STRING:
- /* Do nothing; strings go in the string pool. */
- break;
+ case TYPE_POINTER:
+ {
+ if (maybe_undef_p
+ && t->u.p->u.s.line.file == NULL)
+ {
+ oprintf (d->of, "%*sif (%s) abort();\n", d->indent, "", d->val);
+ break;
+ }
- case TYPE_LANG_STRUCT:
+ if (! length)
{
- type_p ti;
- for (ti = t->u.s.lang_struct; ti; ti = ti->next)
- if (ti->u.s.bitmap & bitmap)
- {
- t = ti;
- break;
- }
- if (ti == NULL)
+ if (! UNION_OR_STRUCT_P (t->u.p)
+ && t->u.p->kind != TYPE_PARAM_STRUCT)
{
- error_at_line (&f->line,
- "structure not defined for this language");
+ error_at_line (d->line,
+ "field `%s' is pointer to unimplemented type",
+ d->val);
break;
}
+
+ d->process_field (t->u.p, d);
}
- /* Fall through... */
- case TYPE_STRUCT:
- case TYPE_UNION:
+ else
{
+ int loopcounter = d->counter++;
+ const char *oldval = d->val;
+ const char *oldprevval3 = d->prev_val[3];
char *newval;
- newval = xasprintf ("%s%s%s", val, dot, f->name);
- write_gc_structure_fields (of, t, newval, val, f->opt, indent,
- &f->line, bitmap, param);
+ oprintf (d->of, "%*sif (%s != NULL) {\n", d->indent, "", d->val);
+ d->indent += 2;
+ oprintf (d->of, "%*ssize_t i%d;\n", d->indent, "", loopcounter);
+ d->process_field(t, d);
+ oprintf (d->of, "%*sfor (i%d = 0; i%d < (size_t)(", d->indent, "",
+ loopcounter, loopcounter);
+ output_escaped_param (d, length, "length");
+ oprintf (d->of, "); i%d++) {\n", loopcounter);
+ d->indent += 2;
+ d->val = newval = xasprintf ("%s[i%d]", oldval, loopcounter);
+ d->used_length = 1;
+ d->prev_val[3] = oldval;
+ walk_type (t->u.p, d);
free (newval);
- break;
+ d->val = oldval;
+ d->prev_val[3] = oldprevval3;
+ d->used_length = 0;
+ d->indent -= 2;
+ oprintf (d->of, "%*s}\n", d->indent, "");
+ d->indent -= 2;
+ oprintf (d->of, "%*s}\n", d->indent, "");
}
+ }
+ break;
- case TYPE_POINTER:
- if (! length)
- {
- if (maybe_undef_p
- && t->u.p->u.s.line.file == NULL)
- oprintf (of, "%*sif (%s%s%s) abort();\n", indent, "",
- val, dot, f->name);
- else if (UNION_OR_STRUCT_P (t->u.p)
- || t->u.p->kind == TYPE_PARAM_STRUCT)
- {
- oprintf (of, "%*sgt_ggc_m_", indent, "");
- output_mangled_typename (of, t->u.p);
- oprintf (of, " (");
- if (needs_cast_p)
- oprintf (of, "(%s %s *)",
- UNION_P (t->u.p) ? "union" : "struct",
- t->u.p->u.s.tag);
- oprintf (of, "%s%s%s);\n", val, dot, f->name);
- }
- else
- error_at_line (&f->line, "field `%s' is pointer to scalar",
- f->name);
- break;
- }
- else if (t->u.p->kind == TYPE_SCALAR
- || t->u.p->kind == TYPE_STRING)
- oprintf (of, "%*sggc_mark (%s%s%s);\n", indent, "",
- val, dot, f->name);
- else
- {
- int loopcounter = ++gc_counter;
-
- oprintf (of, "%*sif (%s%s%s != NULL) {\n", indent, "",
- val, dot, f->name);
- indent += 2;
- oprintf (of, "%*ssize_t i%d;\n", indent, "", loopcounter);
- oprintf (of, "%*sggc_set_mark (%s%s%s);\n", indent, "",
- val, dot, f->name);
- oprintf (of, "%*sfor (i%d = 0; i%d < (size_t)(", indent, "",
- loopcounter, loopcounter);
- output_escaped_param (of, length, val, prev_val, "length", line);
- oprintf (of, "); i%d++) {\n", loopcounter);
- indent += 2;
- switch (t->u.p->kind)
- {
- case TYPE_STRUCT:
- case TYPE_UNION:
- {
- char *newval;
-
- newval = xasprintf ("%s%s%s[i%d]", val, dot, f->name,
- loopcounter);
- write_gc_structure_fields (of, t->u.p, newval, val,
- f->opt, indent, &f->line,
- bitmap, param);
- free (newval);
- break;
- }
- case TYPE_POINTER:
- if (UNION_OR_STRUCT_P (t->u.p->u.p)
- || t->u.p->u.p->kind == TYPE_PARAM_STRUCT)
- {
- oprintf (of, "%*sgt_ggc_m_", indent, "");
- output_mangled_typename (of, t->u.p->u.p);
- oprintf (of, " (%s%s%s[i%d]);\n", val, dot, f->name,
- loopcounter);
- }
- else
- error_at_line (&f->line,
- "field `%s' is array of pointer to scalar",
- f->name);
- break;
- default:
- error_at_line (&f->line,
- "field `%s' is array of unimplemented type",
- f->name);
- break;
- }
- indent -= 2;
- oprintf (of, "%*s}\n", indent, "");
- indent -= 2;
- oprintf (of, "%*s}\n", indent, "");
- }
+ case TYPE_ARRAY:
+ {
+ int loopcounter = d->counter++;
+ const char *oldval = d->val;
+ char *newval;
+
+ /* If it's an array of scalars, we optimise by not generating
+ any code. */
+ if (t->u.a.p->kind == TYPE_SCALAR)
break;
+
+ oprintf (d->of, "%*s{\n", d->indent, "");
+ d->indent += 2;
+ oprintf (d->of, "%*ssize_t i%d;\n", d->indent, "", loopcounter);
+ oprintf (d->of, "%*sfor (i%d = 0; i%d < (size_t)(", d->indent, "",
+ loopcounter, loopcounter);
+ if (length)
+ output_escaped_param (d, length, "length");
+ else
+ oprintf (d->of, "%s", t->u.a.len);
+ oprintf (d->of, "); i%d++) {\n", loopcounter);
+ d->indent += 2;
+ d->val = newval = xasprintf ("%s[i%d]", oldval, loopcounter);
+ d->used_length = 1;
+ walk_type (t->u.a.p, d);
+ free (newval);
+ d->used_length = 0;
+ d->val = oldval;
+ d->indent -= 2;
+ oprintf (d->of, "%*s}\n", d->indent, "");
+ d->indent -= 2;
+ oprintf (d->of, "%*s}\n", d->indent, "");
+ }
+ break;
+
+ case TYPE_STRUCT:
+ case TYPE_UNION:
+ {
+ pair_p f;
+ const char *oldval = d->val;
+ const char *oldprevval1 = d->prev_val[1];
+ const char *oldprevval2 = d->prev_val[2];
+ const int union_p = t->kind == TYPE_UNION;
+ int seen_default_p = 0;
+ options_p o;
+
+ if (! t->u.s.line.file)
+ error_at_line (d->line, "incomplete structure `%s'", t->u.s.tag);
- case TYPE_ARRAY:
+ if ((d->bitmap & t->u.s.bitmap) != d->bitmap)
{
- int loopcounter = ++gc_counter;
- type_p ta;
- int i;
-
- if (! length &&
- (strcmp (t->u.a.len, "0") == 0
- || strcmp (t->u.a.len, "1") == 0))
- error_at_line (&f->line,
- "field `%s' is array of size %s",
- f->name, t->u.a.len);
-
- /* Arrays of scalars can be ignored. */
- for (ta = t; ta->kind == TYPE_ARRAY; ta = ta->u.a.p)
- ;
- if (ta->kind == TYPE_SCALAR
- || ta->kind == TYPE_STRING)
- break;
+ error_at_line (d->line,
+ "structure `%s' defined for mismatching languages",
+ t->u.s.tag);
+ error_at_line (&t->u.s.line, "one structure defined here");
+ }
- oprintf (of, "%*s{\n", indent, "");
- indent += 2;
+ /* Some things may also be defined in the structure's options. */
+ for (o = t->u.s.opt; o; o = o->next)
+ if (! desc && strcmp (o->name, "desc") == 0)
+ desc = (const char *)o->info;
- for (ta = t, i = 0; ta->kind == TYPE_ARRAY; ta = ta->u.a.p, i++)
+ d->prev_val[2] = oldval;
+ d->prev_val[1] = oldprevval2;
+ if (union_p)
+ {
+ if (desc == NULL)
{
- oprintf (of, "%*ssize_t i%d_%d;\n",
- indent, "", loopcounter, i);
- oprintf (of, "%*sconst size_t ilimit%d_%d = (",
- indent, "", loopcounter, i);
- if (i == 0 && length != NULL)
- output_escaped_param (of, length, val, prev_val,
- "length", line);
- else
- oprintf (of, "%s", ta->u.a.len);
- oprintf (of, ");\n");
+ error_at_line (d->line, "missing `desc' option for union `%s'",
+ t->u.s.tag);
+ desc = "1";
}
-
- for (ta = t, i = 0; ta->kind == TYPE_ARRAY; ta = ta->u.a.p, i++)
+ oprintf (d->of, "%*sswitch (", d->indent, "");
+ output_escaped_param (d, desc, "desc");
+ oprintf (d->of, ")\n");
+ d->indent += 2;
+ oprintf (d->of, "%*s{\n", d->indent, "");
+ }
+ for (f = t->u.s.fields; f; f = f->next)
+ {
+ options_p oo;
+ const char *dot = ".";
+ const char *tagid = NULL;
+ int skip_p = 0;
+ int default_p = 0;
+ int use_param_p = 0;
+ char *newval;
+
+ d->reorder_fn = NULL;
+ for (oo = f->opt; oo; oo = oo->next)
+ if (strcmp (oo->name, "dot") == 0)
+ dot = (const char *)oo->info;
+ else if (strcmp (oo->name, "tag") == 0)
+ tagid = (const char *)oo->info;
+ else if (strcmp (oo->name, "skip") == 0)
+ skip_p = 1;
+ else if (strcmp (oo->name, "default") == 0)
+ default_p = 1;
+ else if (strcmp (oo->name, "reorder") == 0)
+ d->reorder_fn = (const char *)oo->info;
+ else if (strncmp (oo->name, "use_param", 9) == 0
+ && (oo->name[9] == '\0' || ISDIGIT (oo->name[9])))
+ use_param_p = 1;
+
+ if (skip_p)
+ continue;
+
+ if (union_p && tagid)
{
- oprintf (of,
- "%*sfor (i%d_%d = 0; i%d_%d < ilimit%d_%d; i%d_%d++) {\n",
- indent, "", loopcounter, i, loopcounter, i,
- loopcounter, i, loopcounter, i);
- indent += 2;
+ oprintf (d->of, "%*scase %s:\n", d->indent, "", tagid);
+ d->indent += 2;
}
-
- if (ta->kind == TYPE_POINTER
- && (UNION_OR_STRUCT_P (ta->u.p)
- || ta->u.p->kind == TYPE_PARAM_STRUCT))
+ else if (union_p && default_p)
{
- oprintf (of, "%*sgt_ggc_m_", indent, "");
- output_mangled_typename (of, ta->u.p);
- oprintf (of, " (%s%s%s", val, dot, f->name);
- for (ta = t, i = 0;
- ta->kind == TYPE_ARRAY;
- ta = ta->u.a.p, i++)
- oprintf (of, "[i%d_%d]", loopcounter, i);
- oprintf (of, ");\n");
+ oprintf (d->of, "%*sdefault:\n", d->indent, "");
+ d->indent += 2;
+ seen_default_p = 1;
}
- else if (ta->kind == TYPE_STRUCT || ta->kind == TYPE_UNION)
+ else if (! union_p && (default_p || tagid))
+ error_at_line (d->line,
+ "can't use `%s' outside a union on field `%s'",
+ default_p ? "default" : "tag", f->name);
+ else if (union_p && ! (default_p || tagid)
+ && f->type->kind == TYPE_SCALAR)
{
- char *newval;
- int len;
-
- len = strlen (val) + strlen (f->name) + 2;
- for (ta = t; ta->kind == TYPE_ARRAY; ta = ta->u.a.p)
- len += sizeof ("[i_]") + 2*6;
-
- newval = xmalloc (len);
- sprintf (newval, "%s%s%s", val, dot, f->name);
- for (ta = t, i = 0;
- ta->kind == TYPE_ARRAY;
- ta = ta->u.a.p, i++)
- sprintf (newval + strlen (newval), "[i%d_%d]",
- loopcounter, i);
- write_gc_structure_fields (of, t->u.p, newval, val,
- f->opt, indent, &f->line, bitmap,
- param);
- free (newval);
+ fprintf (stderr,
+ "%s:%d: warning: field `%s' is missing `tag' or `default' option\n",
+ d->line->file, d->line->line, f->name);
+ continue;
}
- else if (ta->kind == TYPE_POINTER && ta->u.p->kind == TYPE_SCALAR
- && use_param_num != -1 && param == NULL)
- oprintf (of, "%*sabort();\n", indent, "");
- else
- error_at_line (&f->line,
- "field `%s' is array of unimplemented type",
+ else if (union_p && ! (default_p || tagid))
+ error_at_line (d->line,
+ "field `%s' is missing `tag' or `default' option",
f->name);
- for (ta = t, i = 0; ta->kind == TYPE_ARRAY; ta = ta->u.a.p, i++)
+
+ d->line = &f->line;
+ d->val = newval = xasprintf ("%s%s%s", oldval, dot, f->name);
+ d->opt = f->opt;
+
+ if (union_p && use_param_p && d->param == NULL)
+ oprintf (d->of, "%*sabort();\n", d->indent, "");
+ else
+ walk_type (f->type, d);
+
+ free (newval);
+
+ if (union_p)
{
- indent -= 2;
- oprintf (of, "%*s}\n", indent, "");
+ oprintf (d->of, "%*sbreak;\n", d->indent, "");
+ d->indent -= 2;
}
+ }
+ d->reorder_fn = NULL;
- indent -= 2;
- oprintf (of, "%*s}\n", indent, "");
- break;
+ d->val = oldval;
+ d->prev_val[1] = oldprevval1;
+ d->prev_val[2] = oldprevval2;
+
+ if (union_p && ! seen_default_p)
+ {
+ oprintf (d->of, "%*sdefault:\n", d->indent, "");
+ oprintf (d->of, "%*s break;\n", d->indent, "");
+ }
+ if (union_p)
+ {
+ oprintf (d->of, "%*s}\n", d->indent, "");
+ d->indent -= 2;
}
+ }
+ break;
- default:
- error_at_line (&f->line,
- "field `%s' is unimplemented type",
- f->name);
- break;
- }
+ case TYPE_LANG_STRUCT:
+ {
+ type_p nt;
+ for (nt = t->u.s.lang_struct; nt; nt = nt->next)
+ if ((d->bitmap & nt->u.s.bitmap) == d->bitmap)
+ break;
+ if (nt == NULL)
+ error_at_line (d->line, "structure `%s' differs between languages",
+ t->u.s.tag);
+ else
+ walk_type (nt, d);
+ }
+ break;
+
+ case TYPE_PARAM_STRUCT:
+ {
+ type_p *oldparam = d->param;
+
+ d->param = t->u.param_struct.param;
+ walk_type (t->u.param_struct.stru, d);
+ d->param = oldparam;
+ }
+ break;
- if (s->kind == TYPE_UNION)
- {
- oprintf (of, "%*sbreak;\n", indent, "");
- indent -= 2;
- }
+ default:
+ abort ();
}
- if (s->kind == TYPE_UNION)
+}
+
+/* process_field routine for marking routines. */
+
+static void
+write_types_process_field (f, d)
+ type_p f;
+ const struct walk_type_data *d;
+{
+ const struct write_types_data *wtd;
+ wtd = (const struct write_types_data *) d->cookie;
+
+ switch (f->kind)
{
- if (! seen_default)
+ case TYPE_POINTER:
+ oprintf (d->of, "%*s%s (%s", d->indent, "",
+ wtd->subfield_marker_routine, d->val);
+ if (wtd->param_prefix)
{
- oprintf (of, "%*sdefault:\n", indent, "");
- oprintf (of, "%*s break;\n", indent, "");
+ oprintf (d->of, ", %s", d->prev_val[3]);
+ if (d->orig_s)
+ {
+ oprintf (d->of, ", gt_%s_", wtd->param_prefix);
+ output_mangled_typename (d->of, d->orig_s);
+ }
+ else
+ oprintf (d->of, ", gt_%sa_%s", wtd->param_prefix, d->prev_val[0]);
}
- oprintf (of, "%*s}\n", indent, "");
- indent -= 2;
+ oprintf (d->of, ");\n");
+ if (d->reorder_fn && wtd->reorder_note_routine)
+ oprintf (d->of, "%*s%s (%s, %s, %s);\n", d->indent, "",
+ wtd->reorder_note_routine, d->val,
+ d->prev_val[3], d->reorder_fn);
+ break;
+
+ case TYPE_STRING:
+ if (wtd->param_prefix == NULL)
+ break;
+
+ case TYPE_STRUCT:
+ case TYPE_UNION:
+ case TYPE_LANG_STRUCT:
+ case TYPE_PARAM_STRUCT:
+ oprintf (d->of, "%*sgt_%s_", d->indent, "", wtd->prefix);
+ output_mangled_typename (d->of, f);
+ oprintf (d->of, " (%s);\n", d->val);
+ if (d->reorder_fn && wtd->reorder_note_routine)
+ oprintf (d->of, "%*s%s (%s, %s, %s);\n", d->indent, "",
+ wtd->reorder_note_routine, d->val, d->val,
+ d->reorder_fn);
+ break;
+
+ case TYPE_SCALAR:
+ break;
+
+ default:
+ abort ();
}
}
-/* Write out a marker routine for S. PARAM is the parameter from an
- enclosing PARAM_IS option. */
+/* For S, a structure that's part of ORIG_S, and using parameters
+ PARAM, write out a routine that:
+ - Takes a parameter, a void * but actually of type *S
+ - If SEEN_ROUTINE returns nonzero, calls write_types_process_field on each
+ field of S or its substructures and (in some cases) things
+ that are pointed to by S.
+*/
static void
-write_gc_marker_routine_for_structure (orig_s, s, param)
+write_func_for_structure (orig_s, s, param, wtd)
type_p orig_s;
type_p s;
type_p * param;
+ const struct write_types_data *wtd;
{
- outf_p f;
const char *fn = s->u.s.line.file;
int i;
const char *chain_next = NULL;
const char *chain_prev = NULL;
options_p opt;
+ struct walk_type_data d;
/* This is a hack, and not the good kind either. */
for (i = NUM_PARAM - 1; i >= 0; i--)
@@ -1893,7 +1961,8 @@ write_gc_marker_routine_for_structure (orig_s, s, param)
&& UNION_OR_STRUCT_P (param[i]->u.p))
fn = param[i]->u.p->u.s.line.file;
- f = get_output_file_with_visibility (fn);
+ memset (&d, 0, sizeof (d));
+ d.of = get_output_file_with_visibility (fn);
for (opt = s->u.s.opt; opt; opt = opt->next)
if (strcmp (opt->name, "chain_next") == 0)
@@ -1904,80 +1973,113 @@ write_gc_marker_routine_for_structure (orig_s, s, param)
if (chain_prev != NULL && chain_next == NULL)
error_at_line (&s->u.s.line, "chain_prev without chain_next");
- oprintf (f, "\n");
- oprintf (f, "void\n");
+ d.process_field = write_types_process_field;
+ d.cookie = wtd;
+ d.orig_s = orig_s;
+ d.opt = s->u.s.opt;
+ d.line = &s->u.s.line;
+ d.bitmap = s->u.s.bitmap;
+ d.param = param;
+ d.prev_val[0] = "*x";
+ d.prev_val[1] = "not valid postage"; /* guarantee an error */
+ d.prev_val[3] = "x";
+ d.val = "(*x)";
+
+ oprintf (d.of, "\n");
+ oprintf (d.of, "void\n");
if (param == NULL)
- oprintf (f, "gt_ggc_mx_%s", s->u.s.tag);
+ oprintf (d.of, "gt_%sx_%s", wtd->prefix, orig_s->u.s.tag);
else
{
- oprintf (f, "gt_ggc_m_");
- output_mangled_typename (f, orig_s);
+ oprintf (d.of, "gt_%s_", wtd->prefix);
+ output_mangled_typename (d.of, orig_s);
}
- oprintf (f, " (x_p)\n");
- oprintf (f, " void *x_p;\n");
- oprintf (f, "{\n");
- oprintf (f, " %s %s * %sx = (%s %s *)x_p;\n",
+ oprintf (d.of, " (x_p)\n");
+ oprintf (d.of, " void *x_p;\n");
+ oprintf (d.of, "{\n");
+ oprintf (d.of, " %s %s * %sx = (%s %s *)x_p;\n",
s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag,
chain_next == NULL ? "const " : "",
s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
if (chain_next != NULL)
- oprintf (f, " %s %s * xlimit = x;\n",
+ oprintf (d.of, " %s %s * xlimit = x;\n",
s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
if (chain_next == NULL)
- oprintf (f, " if (ggc_test_and_set_mark (x))\n");
+ {
+ oprintf (d.of, " if (%s (x", wtd->marker_routine);
+ if (wtd->param_prefix)
+ {
+ oprintf (d.of, ", x, gt_%s_", wtd->param_prefix);
+ output_mangled_typename (d.of, orig_s);
+ }
+ oprintf (d.of, "))\n");
+ }
else
{
- oprintf (f, " while (ggc_test_and_set_mark (xlimit))\n");
- oprintf (f, " xlimit = (");
- output_escaped_param (f, chain_next, "*xlimit", "*xlimit",
- "chain_next", &s->u.s.line);
- oprintf (f, ");\n");
+ oprintf (d.of, " while (%s (xlimit", wtd->marker_routine);
+ if (wtd->param_prefix)
+ {
+ oprintf (d.of, ", xlimit, gt_%s_", wtd->param_prefix);
+ output_mangled_typename (d.of, orig_s);
+ }
+ oprintf (d.of, "))\n");
+ oprintf (d.of, " xlimit = (");
+ d.prev_val[2] = "*xlimit";
+ output_escaped_param (&d, chain_next, "chain_next");
+ oprintf (d.of, ");\n");
if (chain_prev != NULL)
{
- oprintf (f, " if (x != xlimit)\n");
- oprintf (f, " for (;;)\n");
- oprintf (f, " {\n");
- oprintf (f, " %s %s * const xprev = (",
+ oprintf (d.of, " if (x != xlimit)\n");
+ oprintf (d.of, " for (;;)\n");
+ oprintf (d.of, " {\n");
+ oprintf (d.of, " %s %s * const xprev = (",
s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
- output_escaped_param (f, chain_prev, "*x", "*x",
- "chain_prev", &s->u.s.line);
- oprintf (f, ");\n");
- oprintf (f, " if (xprev == NULL) break;\n");
- oprintf (f, " x = xprev;\n");
- oprintf (f, " ggc_set_mark (xprev);\n");
- oprintf (f, " }\n");
+
+ d.prev_val[2] = "*x";
+ output_escaped_param (&d, chain_prev, "chain_prev");
+ oprintf (d.of, ");\n");
+ oprintf (d.of, " if (xprev == NULL) break;\n");
+ oprintf (d.of, " x = xprev;\n");
+ oprintf (d.of, " (void) %s (xprev",
+ wtd->marker_routine);
+ if (wtd->param_prefix)
+ {
+ oprintf (d.of, ", xprev, gt_%s_", wtd->param_prefix);
+ output_mangled_typename (d.of, orig_s);
+ }
+ oprintf (d.of, ");\n");
+ oprintf (d.of, " }\n");
}
- oprintf (f, " while (x != xlimit)\n");
+ oprintf (d.of, " while (x != xlimit)\n");
}
- oprintf (f, " {\n");
+ oprintf (d.of, " {\n");
- gc_counter = 0;
- write_gc_structure_fields (f, s, "(*x)", "not valid postage",
- s->u.s.opt, 6, &s->u.s.line, s->u.s.bitmap,
- param);
+ d.prev_val[2] = "*x";
+ d.indent = 6;
+ walk_type (s, &d);
if (chain_next != NULL)
{
- oprintf (f, " x = (");
- output_escaped_param (f, chain_next, "*x", "*x",
- "chain_next", &s->u.s.line);
- oprintf (f, ");\n");
+ oprintf (d.of, " x = (");
+ output_escaped_param (&d, chain_next, "chain_next");
+ oprintf (d.of, ");\n");
}
- oprintf (f, " }\n");
- oprintf (f, "}\n");
+ oprintf (d.of, " }\n");
+ oprintf (d.of, "}\n");
}
/* Write out marker routines for STRUCTURES and PARAM_STRUCTS. */
static void
-write_gc_types (structures, param_structs)
+write_types (structures, param_structs, wtd)
type_p structures;
type_p param_structs;
+ const struct write_types_data *wtd;
{
type_p s;
- oprintf (header_file, "\n/* GC marker procedures. */\n");
+ oprintf (header_file, "\n/* %s*/\n", wtd->comment);
for (s = structures; s; s = s->next)
if (s->gc_used == GC_POINTED_TO
|| s->gc_used == GC_MAYBE_POINTED_TO)
@@ -1988,11 +2090,12 @@ write_gc_types (structures, param_structs)
&& s->u.s.line.file == NULL)
continue;
- oprintf (header_file, "#define gt_ggc_m_");
+ oprintf (header_file, "#define gt_%s_", wtd->prefix);
output_mangled_typename (header_file, s);
oprintf (header_file, "(X) do { \\\n");
oprintf (header_file,
- " if (X != NULL) gt_ggc_mx_%s (X);\\\n", s->u.s.tag);
+ " if (X != NULL) gt_%sx_%s (X);\\\n", wtd->prefix,
+ s->u.s.tag);
oprintf (header_file,
" } while (0)\n");
@@ -2004,8 +2107,8 @@ write_gc_types (structures, param_structs)
|| t->kind == TYPE_UNION
|| t->kind == TYPE_LANG_STRUCT)
oprintf (header_file,
- "#define gt_ggc_mx_%s gt_ggc_mx_%s\n",
- s->u.s.tag, t->u.s.tag);
+ "#define gt_%sx_%s gt_%sx_%s\n",
+ wtd->prefix, s->u.s.tag, wtd->prefix, t->u.s.tag);
else
error_at_line (&s->u.s.line,
"structure alias is not a structure");
@@ -2016,8 +2119,8 @@ write_gc_types (structures, param_structs)
/* Declare the marker procedure only once. */
oprintf (header_file,
- "extern void gt_ggc_mx_%s PARAMS ((void *));\n",
- s->u.s.tag);
+ "extern void gt_%sx_%s PARAMS ((void *));\n",
+ wtd->prefix, s->u.s.tag);
if (s->u.s.line.file == NULL)
{
@@ -2030,10 +2133,10 @@ write_gc_types (structures, param_structs)
{
type_p ss;
for (ss = s->u.s.lang_struct; ss; ss = ss->next)
- write_gc_marker_routine_for_structure (s, ss, NULL);
+ write_func_for_structure (s, ss, NULL, wtd);
}
else
- write_gc_marker_routine_for_structure (s, s, NULL);
+ write_func_for_structure (s, s, NULL, wtd);
}
for (s = param_structs; s; s = s->next)
@@ -2043,7 +2146,7 @@ write_gc_types (structures, param_structs)
type_p stru = s->u.param_struct.stru;
/* Declare the marker procedure. */
- oprintf (header_file, "extern void gt_ggc_m_");
+ oprintf (header_file, "extern void gt_%s_", wtd->prefix);
output_mangled_typename (header_file, s);
oprintf (header_file, " PARAMS ((void *));\n");
@@ -2058,10 +2161,193 @@ write_gc_types (structures, param_structs)
{
type_p ss;
for (ss = stru->u.s.lang_struct; ss; ss = ss->next)
- write_gc_marker_routine_for_structure (s, ss, param);
+ write_func_for_structure (s, ss, param, wtd);
+ }
+ else
+ write_func_for_structure (s, stru, param, wtd);
+ }
+}
+
+static const struct write_types_data ggc_wtd =
+{
+ "ggc_m", NULL, "ggc_mark", "ggc_test_and_set_mark", NULL,
+ "GC marker procedures. "
+};
+
+static const struct write_types_data pch_wtd =
+{
+ "pch_n", "pch_p", "gt_pch_note_object", "gt_pch_note_object",
+ "gt_pch_note_reorder",
+ "PCH type-walking procedures. "
+};
+
+/* Write out the local pointer-walking routines. */
+
+/* process_field routine for local pointer-walking. */
+
+static void
+write_types_local_process_field (f, d)
+ type_p f;
+ const struct walk_type_data *d;
+{
+ switch (f->kind)
+ {
+ case TYPE_POINTER:
+ case TYPE_STRUCT:
+ case TYPE_UNION:
+ case TYPE_LANG_STRUCT:
+ case TYPE_PARAM_STRUCT:
+ case TYPE_STRING:
+ oprintf (d->of, "%*sif ((void *)(%s) == this_obj)\n", d->indent, "",
+ d->prev_val[3]);
+ oprintf (d->of, "%*s op (&(%s), cookie);\n", d->indent, "", d->val);
+ break;
+
+ case TYPE_SCALAR:
+ break;
+
+ default:
+ abort ();
+ }
+}
+
+/* For S, a structure that's part of ORIG_S, and using parameters
+ PARAM, write out a routine that:
+ - Is of type gt_note_pointers
+ - If calls PROCESS_FIELD on each field of S or its substructures.
+*/
+
+static void
+write_local_func_for_structure (orig_s, s, param)
+ type_p orig_s;
+ type_p s;
+ type_p * param;
+{
+ const char *fn = s->u.s.line.file;
+ int i;
+ struct walk_type_data d;
+
+ /* This is a hack, and not the good kind either. */
+ for (i = NUM_PARAM - 1; i >= 0; i--)
+ if (param && param[i] && param[i]->kind == TYPE_POINTER
+ && UNION_OR_STRUCT_P (param[i]->u.p))
+ fn = param[i]->u.p->u.s.line.file;
+
+ memset (&d, 0, sizeof (d));
+ d.of = get_output_file_with_visibility (fn);
+
+ d.process_field = write_types_local_process_field;
+ d.opt = s->u.s.opt;
+ d.line = &s->u.s.line;
+ d.bitmap = s->u.s.bitmap;
+ d.param = param;
+ d.prev_val[0] = d.prev_val[2] = "*x";
+ d.prev_val[1] = "not valid postage"; /* guarantee an error */
+ d.prev_val[3] = "x";
+ d.val = "(*x)";
+
+ oprintf (d.of, "\n");
+ oprintf (d.of, "void\n");
+ oprintf (d.of, "gt_pch_p_");
+ output_mangled_typename (d.of, orig_s);
+ oprintf (d.of, " (this_obj, x_p, op, cookie)\n");
+ oprintf (d.of, " void *this_obj ATTRIBUTE_UNUSED;\n");
+ oprintf (d.of, " void *x_p;\n");
+ oprintf (d.of, " gt_pointer_operator op ATTRIBUTE_UNUSED;\n");
+ oprintf (d.of, " void *cookie ATTRIBUTE_UNUSED;\n");
+ oprintf (d.of, "{\n");
+ oprintf (d.of, " %s %s * const x ATTRIBUTE_UNUSED = (%s %s *)x_p;\n",
+ s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag,
+ s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
+ d.indent = 2;
+ walk_type (s, &d);
+ oprintf (d.of, "}\n");
+}
+
+/* Write out local marker routines for STRUCTURES and PARAM_STRUCTS. */
+
+static void
+write_local (structures, param_structs)
+ type_p structures;
+ type_p param_structs;
+{
+ type_p s;
+
+ oprintf (header_file, "\n/* Local pointer-walking routines. */\n");
+ for (s = structures; s; s = s->next)
+ if (s->gc_used == GC_POINTED_TO
+ || s->gc_used == GC_MAYBE_POINTED_TO)
+ {
+ options_p opt;
+
+ if (s->u.s.line.file == NULL)
+ continue;
+
+ for (opt = s->u.s.opt; opt; opt = opt->next)
+ if (strcmp (opt->name, "ptr_alias") == 0)
+ {
+ type_p t = (type_p) opt->info;
+ if (t->kind == TYPE_STRUCT
+ || t->kind == TYPE_UNION
+ || t->kind == TYPE_LANG_STRUCT)
+ {
+ oprintf (header_file, "#define gt_pch_p_");
+ output_mangled_typename (header_file, s);
+ oprintf (header_file, " gt_pch_p_");
+ output_mangled_typename (header_file, t);
+ oprintf (header_file, "\n");
+ }
+ else
+ error_at_line (&s->u.s.line,
+ "structure alias is not a structure");
+ break;
+ }
+ if (opt)
+ continue;
+
+ /* Declare the marker procedure only once. */
+ oprintf (header_file, "extern void gt_pch_p_");
+ output_mangled_typename (header_file, s);
+ oprintf (header_file,
+ "\n PARAMS ((void *, void *, gt_pointer_operator, void *));\n");
+
+ if (s->kind == TYPE_LANG_STRUCT)
+ {
+ type_p ss;
+ for (ss = s->u.s.lang_struct; ss; ss = ss->next)
+ write_local_func_for_structure (s, ss, NULL);
+ }
+ else
+ write_local_func_for_structure (s, s, NULL);
+ }
+
+ for (s = param_structs; s; s = s->next)
+ if (s->gc_used == GC_POINTED_TO)
+ {
+ type_p * param = s->u.param_struct.param;
+ type_p stru = s->u.param_struct.stru;
+
+ /* Declare the marker procedure. */
+ oprintf (header_file, "extern void gt_pch_p_");
+ output_mangled_typename (header_file, s);
+ oprintf (header_file,
+ "\n PARAMS ((void *, void *, gt_pointer_operator, void *));\n");
+
+ if (stru->u.s.line.file == NULL)
+ {
+ fprintf (stderr, "warning: structure `%s' used but not defined\n",
+ s->u.s.tag);
+ continue;
+ }
+
+ if (stru->kind == TYPE_LANG_STRUCT)
+ {
+ type_p ss;
+ for (ss = stru->u.s.lang_struct; ss; ss = ss->next)
+ write_local_func_for_structure (s, ss, param);
}
else
- write_gc_marker_routine_for_structure (s, stru, param);
+ write_local_func_for_structure (s, stru, param);
}
}
@@ -2099,6 +2385,25 @@ write_enum_defn (structures, param_structs)
oprintf (header_file, "};\n");
}
+/* Might T contain any non-pointer elements? */
+
+static int
+contains_scalar_p (t)
+ type_p t;
+{
+ switch (t->kind)
+ {
+ case TYPE_STRING:
+ case TYPE_POINTER:
+ return 0;
+ case TYPE_ARRAY:
+ return contains_scalar_p (t->u.a.p);
+ default:
+ /* Could also check for structures that have no non-pointer
+ fields, but there aren't enough of those to worry about. */
+ return 1;
+ }
+}
/* Mangle FN and print it to F. */
@@ -2128,7 +2433,6 @@ finish_root_table (flp, pfx, lastname, tname, name)
const char *name;
{
struct flist *fli2;
- unsigned started_bitmap = 0;
for (fli2 = flp; fli2; fli2 = fli2->next)
if (fli2->started_p)
@@ -2147,12 +2451,21 @@ finish_root_table (flp, pfx, lastname, tname, name)
if (bitmap & 1)
{
oprintf (base_files[fnum],
- "extern const struct %s gt_ggc_%s_",
+ "extern const struct %s gt_%s_",
tname, pfx);
put_mangled_filename (base_files[fnum], fli2->name);
oprintf (base_files[fnum], "[];\n");
}
}
+
+ {
+ size_t fnum;
+ for (fnum = 0; fnum < NUM_BASE_FILES; fnum++)
+ oprintf (base_files [fnum],
+ "const struct %s * const %s[] = {\n",
+ tname, name);
+ }
+
for (fli2 = flp; fli2; fli2 = fli2->next)
if (fli2->started_p)
@@ -2165,29 +2478,19 @@ finish_root_table (flp, pfx, lastname, tname, name)
for (fnum = 0; bitmap != 0; fnum++, bitmap >>= 1)
if (bitmap & 1)
{
- if (! (started_bitmap & (1 << fnum)))
- {
- oprintf (base_files [fnum],
- "const struct %s * const %s[] = {\n",
- tname, name);
- started_bitmap |= 1 << fnum;
- }
- oprintf (base_files[fnum], " gt_ggc_%s_", pfx);
+ oprintf (base_files[fnum], " gt_%s_", pfx);
put_mangled_filename (base_files[fnum], fli2->name);
oprintf (base_files[fnum], ",\n");
}
}
{
- unsigned bitmap;
- int fnum;
-
- for (bitmap = started_bitmap, fnum = 0; bitmap != 0; fnum++, bitmap >>= 1)
- if (bitmap & 1)
- {
- oprintf (base_files[fnum], " NULL\n");
- oprintf (base_files[fnum], "};\n");
- }
+ size_t fnum;
+ for (fnum = 0; fnum < NUM_BASE_FILES; fnum++)
+ {
+ oprintf (base_files[fnum], " NULL\n");
+ oprintf (base_files[fnum], "};\n");
+ }
}
}
@@ -2197,7 +2500,7 @@ finish_root_table (flp, pfx, lastname, tname, name)
is nonzero iff we are building the root table for hash table caches. */
static void
-write_gc_root (f, v, type, name, has_length, line, if_marked)
+write_root (f, v, type, name, has_length, line, if_marked)
outf_p f;
pair_p v;
type_p type;
@@ -2257,8 +2560,8 @@ write_gc_root (f, v, type, name, has_length, line, if_marked)
char *newname;
newname = xasprintf ("%s.%s.%s",
name, fld->name, validf->name);
- write_gc_root (f, v, validf->type, newname, 0, line,
- if_marked);
+ write_root (f, v, validf->type, newname, 0, line,
+ if_marked);
free (newname);
}
}
@@ -2270,7 +2573,7 @@ write_gc_root (f, v, type, name, has_length, line, if_marked)
{
char *newname;
newname = xasprintf ("%s.%s", name, fld->name);
- write_gc_root (f, v, fld->type, newname, 0, line, if_marked);
+ write_root (f, v, fld->type, newname, 0, line, if_marked);
free (newname);
}
}
@@ -2281,7 +2584,7 @@ write_gc_root (f, v, type, name, has_length, line, if_marked)
{
char *newname;
newname = xasprintf ("%s[0]", name);
- write_gc_root (f, v, type->u.a.p, newname, has_length, line, if_marked);
+ write_root (f, v, type->u.a.p, newname, has_length, line, if_marked);
free (newname);
}
break;
@@ -2309,17 +2612,21 @@ write_gc_root (f, v, type, name, has_length, line, if_marked)
if (! has_length && UNION_OR_STRUCT_P (tp))
{
- oprintf (f, " &gt_ggc_mx_%s\n", tp->u.s.tag);
+ oprintf (f, " &gt_ggc_mx_%s,\n", tp->u.s.tag);
+ oprintf (f, " &gt_pch_nx_%s", tp->u.s.tag);
}
else if (! has_length && tp->kind == TYPE_PARAM_STRUCT)
{
oprintf (f, " &gt_ggc_m_");
output_mangled_typename (f, tp);
+ oprintf (f, ",\n &gt_pch_n_");
+ output_mangled_typename (f, tp);
}
else if (has_length
&& (tp->kind == TYPE_POINTER || UNION_OR_STRUCT_P (tp)))
{
- oprintf (f, " &gt_ggc_ma_%s", name);
+ oprintf (f, " &gt_ggc_ma_%s,\n", name);
+ oprintf (f, " &gt_pch_na_%s", name);
}
else
{
@@ -2333,8 +2640,19 @@ write_gc_root (f, v, type, name, has_length, line, if_marked)
}
break;
- case TYPE_SCALAR:
case TYPE_STRING:
+ {
+ oprintf (f, " {\n");
+ oprintf (f, " &%s,\n", name);
+ oprintf (f, " 1, \n");
+ oprintf (f, " sizeof (%s),\n", v->name);
+ oprintf (f, " &gt_ggc_m_S,\n");
+ oprintf (f, " &gt_pch_n_S\n");
+ oprintf (f, " },\n");
+ }
+ break;
+
+ case TYPE_SCALAR:
break;
default:
@@ -2344,10 +2662,64 @@ write_gc_root (f, v, type, name, has_length, line, if_marked)
}
}
+/* This generates a routine to walk an array. */
+
+static void
+write_array (f, v, wtd)
+ outf_p f;
+ pair_p v;
+ const struct write_types_data *wtd;
+{
+ struct walk_type_data d;
+ char *prevval3;
+
+ memset (&d, 0, sizeof (d));
+ d.of = f;
+ d.cookie = wtd;
+ d.indent = 2;
+ d.line = &v->line;
+ d.opt = v->opt;
+ d.bitmap = get_base_file_bitmap (v->line.file);
+ d.param = NULL;
+
+ d.prev_val[3] = prevval3 = xasprintf ("&%s", v->name);
+
+ if (wtd->param_prefix)
+ {
+ oprintf (f, "static void gt_%sa_%s\n", wtd->param_prefix, v->name);
+ oprintf (f,
+ " PARAMS ((void *, void *, gt_pointer_operator, void *));\n");
+ oprintf (f, "static void gt_%sa_%s (this_obj, x_p, op, cookie)\n",
+ wtd->param_prefix, v->name);
+ oprintf (d.of, " void *this_obj ATTRIBUTE_UNUSED;\n");
+ oprintf (d.of, " void *x_p ATTRIBUTE_UNUSED;\n");
+ oprintf (d.of, " gt_pointer_operator op ATTRIBUTE_UNUSED;\n");
+ oprintf (d.of, " void *cookie ATTRIBUTE_UNUSED;\n");
+ oprintf (d.of, "{\n");
+ d.prev_val[0] = d.prev_val[1] = d.prev_val[2] = d.val = v->name;
+ d.process_field = write_types_local_process_field;
+ walk_type (v->type, &d);
+ oprintf (f, "}\n\n");
+ }
+
+ d.opt = v->opt;
+ oprintf (f, "static void gt_%sa_%s PARAMS ((void *));\n",
+ wtd->prefix, v->name);
+ oprintf (f, "static void\ngt_%sa_%s (x_p)\n",
+ wtd->prefix, v->name);
+ oprintf (f, " void *x_p ATTRIBUTE_UNUSED;\n");
+ oprintf (f, "{\n");
+ d.prev_val[0] = d.prev_val[1] = d.prev_val[2] = d.val = v->name;
+ d.process_field = write_types_process_field;
+ walk_type (v->type, &d);
+ free (prevval3);
+ oprintf (f, "}\n\n");
+}
+
/* Output a table describing the locations and types of VARIABLES. */
static void
-write_gc_roots (variables)
+write_roots (variables)
pair_p variables;
{
pair_p v;
@@ -2400,52 +2772,8 @@ write_gc_roots (variables)
&& (v->type->u.p->kind == TYPE_POINTER
|| v->type->u.p->kind == TYPE_STRUCT))
{
- oprintf (f, "static void gt_ggc_ma_%s PARAMS ((void *));\n",
- v->name);
- oprintf (f, "static void\ngt_ggc_ma_%s (x_p)\n void *x_p;\n",
- v->name);
- oprintf (f, "{\n");
- oprintf (f, " size_t i;\n");
-
- if (v->type->u.p->kind == TYPE_POINTER)
- {
- type_p s = v->type->u.p->u.p;
-
- oprintf (f, " %s %s ** const x = (%s %s **)x_p;\n",
- s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag,
- s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
- oprintf (f, " if (ggc_test_and_set_mark (x))\n");
- oprintf (f, " for (i = 0; i < (%s); i++)\n", length);
- if (! UNION_OR_STRUCT_P (s)
- && ! s->kind == TYPE_PARAM_STRUCT)
- {
- error_at_line (&v->line,
- "global `%s' has unsupported ** type",
- v->name);
- continue;
- }
-
- oprintf (f, " gt_ggc_m_");
- output_mangled_typename (f, s);
- oprintf (f, " (x[i]);\n");
- }
- else
- {
- type_p s = v->type->u.p;
-
- oprintf (f, " %s %s * const x = (%s %s *)x_p;\n",
- s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag,
- s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
- oprintf (f, " if (ggc_test_and_set_mark (x))\n");
- oprintf (f, " for (i = 0; i < (%s); i++)\n", length);
- oprintf (f, " {\n");
- write_gc_structure_fields (f, s, "x[i]", "x[i]",
- v->opt, 8, &v->line, s->u.s.bitmap,
- NULL);
- oprintf (f, " }\n");
- }
-
- oprintf (f, "}\n\n");
+ write_array (f, v, &ggc_wtd);
+ write_array (f, v, &pch_wtd);
}
}
@@ -2479,10 +2807,10 @@ write_gc_roots (variables)
oprintf (f, "[] = {\n");
}
- write_gc_root (f, v, v->type, v->name, length_p, &v->line, NULL);
+ write_root (f, v, v->type, v->name, length_p, &v->line, NULL);
}
- finish_root_table (flp, "r", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
+ finish_root_table (flp, "ggc_r", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
"gt_ggc_rtab");
for (v = variables; v; v = v->next)
@@ -2513,11 +2841,11 @@ write_gc_roots (variables)
oprintf (f, "[] = {\n");
}
- oprintf (f, " { &%s, 1, sizeof (%s), NULL },\n",
+ oprintf (f, " { &%s, 1, sizeof (%s), NULL, NULL },\n",
v->name, v->name);
}
- finish_root_table (flp, "rd", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
+ finish_root_table (flp, "ggc_rd", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
"gt_ggc_deletable_rtab");
for (v = variables; v; v = v->next)
@@ -2557,12 +2885,84 @@ write_gc_roots (variables)
oprintf (f, "[] = {\n");
}
- write_gc_root (f, v, v->type->u.p->u.param_struct.param[0],
+ write_root (f, v, v->type->u.p->u.param_struct.param[0],
v->name, length_p, &v->line, if_marked);
}
- finish_root_table (flp, "rc", "LAST_GGC_CACHE_TAB", "ggc_cache_tab",
+ finish_root_table (flp, "ggc_rc", "LAST_GGC_CACHE_TAB", "ggc_cache_tab",
"gt_ggc_cache_rtab");
+
+ for (v = variables; v; v = v->next)
+ {
+ outf_p f = get_output_file_with_visibility (v->line.file);
+ struct flist *fli;
+ int length_p = 0;
+ int if_marked_p = 0;
+ options_p o;
+
+ for (o = v->opt; o; o = o->next)
+ if (strcmp (o->name, "length") == 0)
+ length_p = 1;
+ else if (strcmp (o->name, "if_marked") == 0)
+ if_marked_p = 1;
+
+ if (! if_marked_p)
+ continue;
+
+ for (fli = flp; fli; fli = fli->next)
+ if (fli->f == f)
+ break;
+ if (! fli->started_p)
+ {
+ fli->started_p = 1;
+
+ oprintf (f, "const struct ggc_root_tab gt_pch_rc_");
+ put_mangled_filename (f, v->line.file);
+ oprintf (f, "[] = {\n");
+ }
+
+ write_root (f, v, v->type, v->name, length_p, &v->line, NULL);
+ }
+
+ finish_root_table (flp, "pch_rc", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
+ "gt_pch_cache_rtab");
+
+ for (v = variables; v; v = v->next)
+ {
+ outf_p f = get_output_file_with_visibility (v->line.file);
+ struct flist *fli;
+ int skip_p = 0;
+ options_p o;
+
+ for (o = v->opt; o; o = o->next)
+ if (strcmp (o->name, "deletable") == 0
+ || strcmp (o->name, "if_marked") == 0)
+ skip_p = 1;
+
+ if (skip_p)
+ continue;
+
+ if (! contains_scalar_p (v->type))
+ continue;
+
+ for (fli = flp; fli; fli = fli->next)
+ if (fli->f == f)
+ break;
+ if (! fli->started_p)
+ {
+ fli->started_p = 1;
+
+ oprintf (f, "const struct ggc_root_tab gt_pch_rs_");
+ put_mangled_filename (f, v->line.file);
+ oprintf (f, "[] = {\n");
+ }
+
+ oprintf (f, " { &%s, 1, sizeof (%s), NULL, NULL },\n",
+ v->name, v->name);
+ }
+
+ finish_root_table (flp, "pch_rs", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
+ "gt_pch_scalar_rtab");
}
@@ -2616,8 +3016,10 @@ main(argc, argv)
open_base_files ();
write_enum_defn (structures, param_structs);
- write_gc_types (structures, param_structs);
- write_gc_roots (variables);
+ write_types (structures, param_structs, &ggc_wtd);
+ write_types (structures, param_structs, &pch_wtd);
+ write_local (structures, param_structs);
+ write_roots (variables);
write_rtx_next ();
close_output_files ();
diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c
index f353617f4f7..ed6d3b45a85 100644
--- a/gcc/ggc-common.c
+++ b/gcc/ggc-common.c
@@ -24,14 +24,14 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tm.h"
-#include "rtl.h"
-#include "tree.h"
-#include "tm_p.h"
#include "hashtab.h"
-#include "varray.h"
#include "ggc.h"
-#include "langhooks.h"
+#include "toplev.h"
+
+#ifdef HAVE_MMAP_FILE
+# include <sys/mman.h>
+#endif
+
#ifdef ENABLE_VALGRIND_CHECKING
#include <valgrind.h>
#else
@@ -42,46 +42,20 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
/* Statistics about the allocation. */
static ggc_statistics *ggc_stats;
+struct traversal_state;
+
static int ggc_htab_delete PARAMS ((void **, void *));
+static hashval_t saving_htab_hash PARAMS ((const PTR));
+static int saving_htab_eq PARAMS ((const PTR, const PTR));
+static int call_count PARAMS ((void **, void *));
+static int call_alloc PARAMS ((void **, void *));
+static int compare_ptr_data PARAMS ((const void *, const void *));
+static void relocate_ptrs PARAMS ((void *, void *));
+static void write_pch_globals PARAMS ((const struct ggc_root_tab * const *tab,
+ struct traversal_state *state));
/* Maintain global roots that are preserved during GC. */
-/* Global roots that are preserved during calls to gc. */
-
-struct ggc_root
-{
- struct ggc_root *next;
- void *base;
- int nelt;
- int size;
- void (*cb) PARAMS ((void *));
-};
-
-static struct ggc_root *roots;
-
-/* Add BASE as a new garbage collection root. It is an array of
- length NELT with each element SIZE bytes long. CB is a
- function that will be called with a pointer to each element
- of the array; it is the intention that CB call the appropriate
- routine to mark gc-able memory for that element. */
-
-void
-ggc_add_root (base, nelt, size, cb)
- void *base;
- int nelt, size;
- void (*cb) PARAMS ((void *));
-{
- struct ggc_root *x = (struct ggc_root *) xmalloc (sizeof (*x));
-
- x->next = roots;
- x->base = base;
- x->nelt = nelt;
- x->size = size;
- x->cb = cb;
-
- roots = x;
-}
-
/* Process a slot of an htab by deleting it if it has not been marked. */
static int
@@ -104,7 +78,6 @@ ggc_htab_delete (slot, info)
void
ggc_mark_roots ()
{
- struct ggc_root *x;
const struct ggc_root_tab *const *rt;
const struct ggc_root_tab *rti;
const struct ggc_cache_tab *const *ct;
@@ -120,23 +93,18 @@ ggc_mark_roots ()
for (i = 0; i < rti->nelt; i++)
(*rti->cb)(*(void **)((char *)rti->base + rti->stride * i));
- for (x = roots; x != NULL; x = x->next)
- {
- char *elt = x->base;
- int s = x->size, n = x->nelt;
- void (*cb) PARAMS ((void *)) = x->cb;
- int i;
-
- for (i = 0; i < n; ++i, elt += s)
- (*cb)(elt);
- }
+ ggc_mark_stringpool ();
/* Now scan all hash tables that have objects which are to be deleted if
they are not already marked. */
for (ct = gt_ggc_cache_rtab; *ct; ct++)
for (cti = *ct; cti->base != NULL; cti++)
if (*cti->base)
- htab_traverse (*cti->base, ggc_htab_delete, (PTR) cti);
+ {
+ ggc_set_mark (*cti->base);
+ htab_traverse (*cti->base, ggc_htab_delete, (PTR) cti);
+ ggc_set_mark ((*cti->base)->entries);
+ }
}
/* Allocate a block of memory, then clear it. */
@@ -204,6 +172,26 @@ ggc_calloc (s1, s2)
return ggc_alloc_cleared (s1 * s2);
}
+/* These are for splay_tree_new_ggc. */
+PTR
+ggc_splay_alloc (sz, nl)
+ int sz;
+ PTR nl;
+{
+ if (nl != NULL)
+ abort ();
+ return ggc_alloc (sz);
+}
+
+void
+ggc_splay_dont_free (x, nl)
+ PTR x ATTRIBUTE_UNUSED;
+ PTR nl;
+{
+ if (nl != NULL)
+ abort ();
+}
+
/* Print statistics that are independent of the collector in use. */
#define SCALE(x) ((unsigned long) ((x) < 1024*10 \
? (x) \
@@ -214,11 +202,9 @@ ggc_calloc (s1, s2)
void
ggc_print_common_statistics (stream, stats)
- FILE *stream;
+ FILE *stream ATTRIBUTE_UNUSED;
ggc_statistics *stats;
{
- int code;
-
/* Set the pointer so that during collection we will actually gather
the statistics. */
ggc_stats = stats;
@@ -226,58 +212,415 @@ ggc_print_common_statistics (stream, stats)
/* Then do one collection to fill in the statistics. */
ggc_collect ();
- /* Total the statistics. */
- for (code = 0; code < MAX_TREE_CODES; ++code)
+ /* At present, we don't really gather any interesting statistics. */
+
+ /* Don't gather statistics any more. */
+ ggc_stats = NULL;
+}
+
+/* Functions for saving and restoring GCable memory to disk. */
+
+static htab_t saving_htab;
+
+struct ptr_data
+{
+ void *obj;
+ void *note_ptr_cookie;
+ gt_note_pointers note_ptr_fn;
+ gt_handle_reorder reorder_fn;
+ size_t size;
+ void *new_addr;
+};
+
+#define POINTER_HASH(x) (hashval_t)((long)x >> 3)
+
+/* Register an object in the hash table. */
+
+int
+gt_pch_note_object (obj, note_ptr_cookie, note_ptr_fn)
+ void *obj;
+ void *note_ptr_cookie;
+ gt_note_pointers note_ptr_fn;
+{
+ struct ptr_data **slot;
+
+ if (obj == NULL || obj == (void *) 1)
+ return 0;
+
+ slot = (struct ptr_data **)
+ htab_find_slot_with_hash (saving_htab, obj, POINTER_HASH (obj),
+ INSERT);
+ if (*slot != NULL)
+ {
+ if ((*slot)->note_ptr_fn != note_ptr_fn
+ || (*slot)->note_ptr_cookie != note_ptr_cookie)
+ abort ();
+ return 0;
+ }
+
+ *slot = xcalloc (sizeof (struct ptr_data), 1);
+ (*slot)->obj = obj;
+ (*slot)->note_ptr_fn = note_ptr_fn;
+ (*slot)->note_ptr_cookie = note_ptr_cookie;
+ if (note_ptr_fn == gt_pch_p_S)
+ (*slot)->size = strlen (obj) + 1;
+ else
+ (*slot)->size = ggc_get_size (obj);
+ return 1;
+}
+
+/* Register an object in the hash table. */
+
+void
+gt_pch_note_reorder (obj, note_ptr_cookie, reorder_fn)
+ void *obj;
+ void *note_ptr_cookie;
+ gt_handle_reorder reorder_fn;
+{
+ struct ptr_data *data;
+
+ if (obj == NULL || obj == (void *) 1)
+ return;
+
+ data = htab_find_with_hash (saving_htab, obj, POINTER_HASH (obj));
+ if (data == NULL
+ || data->note_ptr_cookie != note_ptr_cookie)
+ abort ();
+
+ data->reorder_fn = reorder_fn;
+}
+
+/* Hash and equality functions for saving_htab, callbacks for htab_create. */
+
+static hashval_t
+saving_htab_hash (p)
+ const PTR p;
+{
+ return POINTER_HASH (((struct ptr_data *)p)->obj);
+}
+
+static int
+saving_htab_eq (p1, p2)
+ const PTR p1;
+ const PTR p2;
+{
+ return ((struct ptr_data *)p1)->obj == p2;
+}
+
+/* Handy state for the traversal functions. */
+
+struct traversal_state
+{
+ FILE *f;
+ struct ggc_pch_data *d;
+ size_t count;
+ struct ptr_data **ptrs;
+ size_t ptrs_i;
+};
+
+/* Callbacks for htab_traverse. */
+
+static int
+call_count (slot, state_p)
+ void **slot;
+ void *state_p;
+{
+ struct ptr_data *d = (struct ptr_data *)*slot;
+ struct traversal_state *state = (struct traversal_state *)state_p;
+
+ ggc_pch_count_object (state->d, d->obj, d->size);
+ state->count++;
+ return 1;
+}
+
+static int
+call_alloc (slot, state_p)
+ void **slot;
+ void *state_p;
+{
+ struct ptr_data *d = (struct ptr_data *)*slot;
+ struct traversal_state *state = (struct traversal_state *)state_p;
+
+ d->new_addr = ggc_pch_alloc_object (state->d, d->obj, d->size);
+ state->ptrs[state->ptrs_i++] = d;
+ return 1;
+}
+
+/* Callback for qsort. */
+
+static int
+compare_ptr_data (p1_p, p2_p)
+ const void *p1_p;
+ const void *p2_p;
+{
+ struct ptr_data *p1 = *(struct ptr_data *const *)p1_p;
+ struct ptr_data *p2 = *(struct ptr_data *const *)p2_p;
+ return (((size_t)p1->new_addr > (size_t)p2->new_addr)
+ - ((size_t)p1->new_addr < (size_t)p2->new_addr));
+}
+
+/* Callbacks for note_ptr_fn. */
+
+static void
+relocate_ptrs (ptr_p, state_p)
+ void *ptr_p;
+ void *state_p;
+{
+ void **ptr = (void **)ptr_p;
+ struct traversal_state *state ATTRIBUTE_UNUSED
+ = (struct traversal_state *)state_p;
+ struct ptr_data *result;
+
+ if (*ptr == NULL || *ptr == (void *)1)
+ return;
+
+ result = htab_find_with_hash (saving_htab, *ptr, POINTER_HASH (*ptr));
+ if (result == NULL)
+ abort ();
+ *ptr = result->new_addr;
+}
+
+/* Write out, after relocation, the pointers in TAB. */
+static void
+write_pch_globals (tab, state)
+ const struct ggc_root_tab * const *tab;
+ struct traversal_state *state;
+{
+ const struct ggc_root_tab *const *rt;
+ const struct ggc_root_tab *rti;
+ size_t i;
+
+ for (rt = tab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ for (i = 0; i < rti->nelt; i++)
+ {
+ void *ptr = *(void **)((char *)rti->base + rti->stride * i);
+ struct ptr_data *new_ptr;
+ if (ptr == NULL || ptr == (void *)1)
+ {
+ if (fwrite (&ptr, sizeof (void *), 1, state->f)
+ != 1)
+ fatal_io_error ("can't write PCH file");
+ }
+ else
+ {
+ new_ptr = htab_find_with_hash (saving_htab, ptr,
+ POINTER_HASH (ptr));
+ if (fwrite (&new_ptr->new_addr, sizeof (void *), 1, state->f)
+ != 1)
+ fatal_io_error ("can't write PCH file");
+ }
+ }
+}
+
+/* Hold the information we need to mmap the file back in. */
+
+struct mmap_info
+{
+ size_t offset;
+ size_t size;
+ void *preferred_base;
+};
+
+/* Write out the state of the compiler to F. */
+
+void
+gt_pch_save (f)
+ FILE *f;
+{
+ const struct ggc_root_tab *const *rt;
+ const struct ggc_root_tab *rti;
+ size_t i;
+ struct traversal_state state;
+ char *this_object = NULL;
+ size_t this_object_size = 0;
+ struct mmap_info mmi;
+ size_t page_size = getpagesize();
+
+ gt_pch_save_stringpool ();
+
+ saving_htab = htab_create (50000, saving_htab_hash, saving_htab_eq, free);
+
+ for (rt = gt_ggc_rtab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ for (i = 0; i < rti->nelt; i++)
+ (*rti->pchw)(*(void **)((char *)rti->base + rti->stride * i));
+
+ for (rt = gt_pch_cache_rtab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ for (i = 0; i < rti->nelt; i++)
+ (*rti->pchw)(*(void **)((char *)rti->base + rti->stride * i));
+
+ /* Prepare the objects for writing, determine addresses and such. */
+ state.f = f;
+ state.d = init_ggc_pch();
+ state.count = 0;
+ htab_traverse (saving_htab, call_count, &state);
+
+ mmi.size = ggc_pch_total_size (state.d);
+
+ /* Try to arrange things so that no relocation is necessary,
+ but don't try very hard. On most platforms, this will always work,
+ and on the rest it's a lot of work to do better. */
+#if HAVE_MMAP_FILE
+ mmi.preferred_base = mmap (NULL, mmi.size,
+ PROT_READ | PROT_WRITE, MAP_PRIVATE,
+ fileno (state.f), 0);
+ if (mmi.preferred_base == (void *)-1)
+ mmi.preferred_base = NULL;
+ else
+ munmap (mmi.preferred_base, mmi.size);
+#else /* HAVE_MMAP_FILE */
+ mmi.preferred_base = NULL;
+#endif /* HAVE_MMAP_FILE */
+
+ ggc_pch_this_base (state.d, mmi.preferred_base);
+
+ state.ptrs = xmalloc (state.count * sizeof (*state.ptrs));
+ state.ptrs_i = 0;
+ htab_traverse (saving_htab, call_alloc, &state);
+ qsort (state.ptrs, state.count, sizeof (*state.ptrs), compare_ptr_data);
+
+ /* Write out all the scalar variables. */
+ for (rt = gt_pch_scalar_rtab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ if (fwrite (rti->base, rti->stride, 1, f) != 1)
+ fatal_io_error ("can't write PCH file");
+
+ /* Write out all the global pointers, after translation. */
+ write_pch_globals (gt_ggc_rtab, &state);
+ write_pch_globals (gt_pch_cache_rtab, &state);
+
+ ggc_pch_prepare_write (state.d, state.f);
+
+ /* Pad the PCH file so that the mmaped area starts on a page boundary. */
+ {
+ off_t o;
+ o = ftello (state.f) + sizeof (mmi);
+ if (o == (off_t) -1)
+ fatal_io_error ("can't get position in PCH file");
+ mmi.offset = page_size - o % page_size;
+ if (mmi.offset == page_size)
+ mmi.offset = 0;
+ mmi.offset += o;
+ }
+ if (fwrite (&mmi, sizeof (mmi), 1, state.f) != 1)
+ fatal_io_error ("can't write PCH file");
+ if (mmi.offset != 0
+ && fseek (state.f, mmi.offset, SEEK_SET) != 0)
+ fatal_io_error ("can't write padding to PCH file");
+
+ /* Actually write out the objects. */
+ for (i = 0; i < state.count; i++)
{
- stats->total_num_trees += stats->num_trees[code];
- stats->total_size_trees += stats->size_trees[code];
+ if (this_object_size < state.ptrs[i]->size)
+ {
+ this_object_size = state.ptrs[i]->size;
+ this_object = xrealloc (this_object, this_object_size);
+ }
+ memcpy (this_object, state.ptrs[i]->obj, state.ptrs[i]->size);
+ if (state.ptrs[i]->reorder_fn != NULL)
+ state.ptrs[i]->reorder_fn (state.ptrs[i]->obj,
+ state.ptrs[i]->note_ptr_cookie,
+ relocate_ptrs, &state);
+ state.ptrs[i]->note_ptr_fn (state.ptrs[i]->obj,
+ state.ptrs[i]->note_ptr_cookie,
+ relocate_ptrs, &state);
+ ggc_pch_write_object (state.d, state.f, state.ptrs[i]->obj,
+ state.ptrs[i]->new_addr, state.ptrs[i]->size);
+ if (state.ptrs[i]->note_ptr_fn != gt_pch_p_S)
+ memcpy (state.ptrs[i]->obj, this_object, state.ptrs[i]->size);
}
- for (code = 0; code < NUM_RTX_CODE; ++code)
+ ggc_pch_finish (state.d, state.f);
+
+ free (state.ptrs);
+ htab_delete (saving_htab);
+}
+
+/* Read the state of the compiler back in from F. */
+
+void
+gt_pch_restore (f)
+ FILE *f;
+{
+ const struct ggc_root_tab *const *rt;
+ const struct ggc_root_tab *rti;
+ size_t i;
+ struct mmap_info mmi;
+ void *addr;
+
+ /* Delete any deletable objects. This makes ggc_pch_read much
+ faster, as it can be sure that no GCable objects remain other
+ than the ones just read in. */
+ for (rt = gt_ggc_deletable_rtab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ memset (rti->base, 0, rti->stride);
+
+ /* Read in all the scalar variables. */
+ for (rt = gt_pch_scalar_rtab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ if (fread (rti->base, rti->stride, 1, f) != 1)
+ fatal_io_error ("can't read PCH file");
+
+ /* Read in all the global pointers, in 6 easy loops. */
+ for (rt = gt_ggc_rtab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ for (i = 0; i < rti->nelt; i++)
+ if (fread ((char *)rti->base + rti->stride * i,
+ sizeof (void *), 1, f) != 1)
+ fatal_io_error ("can't read PCH file");
+
+ for (rt = gt_pch_cache_rtab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ for (i = 0; i < rti->nelt; i++)
+ if (fread ((char *)rti->base + rti->stride * i,
+ sizeof (void *), 1, f) != 1)
+ fatal_io_error ("can't read PCH file");
+
+ if (fread (&mmi, sizeof (mmi), 1, f) != 1)
+ fatal_io_error ("can't read PCH file");
+
+#if HAVE_MMAP_FILE
+ addr = mmap (mmi.preferred_base, mmi.size,
+ PROT_READ | PROT_WRITE, MAP_PRIVATE,
+ fileno (f), mmi.offset);
+#else
+ addr = (void *)-1;
+#endif
+ if (addr == (void *)-1)
{
- stats->total_num_rtxs += stats->num_rtxs[code];
- stats->total_size_rtxs += stats->size_rtxs[code];
+ addr = xmalloc (mmi.size);
+ if (fseek (f, mmi.offset, SEEK_SET) != 0
+ || fread (&mmi, mmi.size, 1, f) != 1)
+ fatal_io_error ("can't read PCH file");
}
+ else if (fseek (f, mmi.offset + mmi.size, SEEK_SET) != 0)
+ fatal_io_error ("can't read PCH file");
- /* Print the statistics for trees. */
- fprintf (stream, "\n%-17s%10s %16s %10s\n", "Tree",
- "Number", "Bytes", "% Total");
- for (code = 0; code < MAX_TREE_CODES; ++code)
- if (ggc_stats->num_trees[code])
- {
- fprintf (stream, "%-17s%10u%16ld%c %10.3f\n",
- tree_code_name[code],
- ggc_stats->num_trees[code],
- SCALE (ggc_stats->size_trees[code]),
- LABEL (ggc_stats->size_trees[code]),
- (100 * ((double) ggc_stats->size_trees[code])
- / ggc_stats->total_size_trees));
- }
- fprintf (stream,
- "%-17s%10u%16ld%c\n", "Total",
- ggc_stats->total_num_trees,
- SCALE (ggc_stats->total_size_trees),
- LABEL (ggc_stats->total_size_trees));
-
- /* Print the statistics for RTL. */
- fprintf (stream, "\n%-17s%10s %16s %10s\n", "RTX",
- "Number", "Bytes", "% Total");
- for (code = 0; code < NUM_RTX_CODE; ++code)
- if (ggc_stats->num_rtxs[code])
- {
- fprintf (stream, "%-17s%10u%16ld%c %10.3f\n",
- rtx_name[code],
- ggc_stats->num_rtxs[code],
- SCALE (ggc_stats->size_rtxs[code]),
- LABEL (ggc_stats->size_rtxs[code]),
- (100 * ((double) ggc_stats->size_rtxs[code])
- / ggc_stats->total_size_rtxs));
- }
- fprintf (stream,
- "%-17s%10u%16ld%c\n", "Total",
- ggc_stats->total_num_rtxs,
- SCALE (ggc_stats->total_size_rtxs),
- LABEL (ggc_stats->total_size_rtxs));
+ ggc_pch_read (f, addr);
- /* Don't gather statistics any more. */
- ggc_stats = NULL;
+ if (addr != mmi.preferred_base)
+ {
+ for (rt = gt_ggc_rtab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ for (i = 0; i < rti->nelt; i++)
+ {
+ char **ptr = (char **)((char *)rti->base + rti->stride * i);
+ if (*ptr != NULL)
+ *ptr += (size_t)addr - (size_t)mmi.preferred_base;
+ }
+
+ for (rt = gt_pch_cache_rtab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ for (i = 0; i < rti->nelt; i++)
+ {
+ char **ptr = (char **)((char *)rti->base + rti->stride * i);
+ if (*ptr != NULL)
+ *ptr += (size_t)addr - (size_t)mmi.preferred_base;
+ }
+
+ sorry ("had to relocate PCH");
+ }
+
+ gt_pch_restore_stringpool ();
}
diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
index 537f302578a..a150c5a88e6 100644
--- a/gcc/ggc-page.c
+++ b/gcc/ggc-page.c
@@ -1,5 +1,5 @@
/* "Bag-of-pages" garbage collector for the GNU compiler.
- Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
@@ -147,6 +147,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
the indicated ORDER. */
#define OBJECTS_PER_PAGE(ORDER) objects_per_page_table[ORDER]
+/* The number of objects in P. */
+#define OBJECTS_IN_PAGE(P) ((P)->bytes / OBJECT_SIZE ((P)->order))
+
/* The size of an object on a page of the indicated ORDER. */
#define OBJECT_SIZE(ORDER) object_size_table[ORDER]
@@ -202,6 +205,15 @@ struct max_alignment {
#define MAX_ALIGNMENT (offsetof (struct max_alignment, u))
+/* Compute the smallest nonnegative number which when added to X gives
+ a multiple of F. */
+
+#define ROUND_UP_VALUE(x, f) ((f) - 1 - ((f) - 1 + (x)) % (f))
+
+/* Compute the smallest multiple of F that is >= X. */
+
+#define ROUND_UP(x, f) (CEIL (x, f) * (f))
+
/* The Ith entry is the number of objects on a page or order I. */
static unsigned objects_per_page_table[NUM_ORDERS];
@@ -1172,7 +1184,7 @@ init_ggc ()
/* If S is not a multiple of the MAX_ALIGNMENT, then round it up
so that we're sure of getting aligned memory. */
- s = CEIL (s, MAX_ALIGNMENT) * MAX_ALIGNMENT;
+ s = ROUND_UP (s, MAX_ALIGNMENT);
object_size_table[order] = s;
}
@@ -1225,7 +1237,7 @@ ggc_recalculate_in_use_p (p)
/* Because the past-the-end bit in in_use_p is always set, we
pretend there is one additional object. */
- num_objects = OBJECTS_PER_PAGE (p->order) + 1;
+ num_objects = OBJECTS_IN_PAGE (p) + 1;
/* Reset the free object count. */
p->num_free_objects = num_objects;
@@ -1294,12 +1306,13 @@ clear_marks ()
for (order = 2; order < NUM_ORDERS; order++)
{
- size_t num_objects = OBJECTS_PER_PAGE (order);
- size_t bitmap_size = BITMAP_SIZE (num_objects + 1);
page_entry *p;
for (p = G.pages[order]; p != NULL; p = p->next)
{
+ size_t num_objects = OBJECTS_IN_PAGE (p);
+ size_t bitmap_size = BITMAP_SIZE (num_objects + 1);
+
#ifdef ENABLE_CHECKING
/* The data should be page-aligned. */
if ((size_t) p->page & (G.pagesize - 1))
@@ -1342,7 +1355,7 @@ sweep_pages ()
placed at the end of the list. */
page_entry * const last = G.page_tails[order];
- size_t num_objects = OBJECTS_PER_PAGE (order);
+ size_t num_objects;
size_t live_objects;
page_entry *p, *previous;
int done;
@@ -1358,6 +1371,8 @@ sweep_pages ()
/* Loop until all entries have been examined. */
done = (p == last);
+
+ num_objects = OBJECTS_IN_PAGE (p);
/* Add all live objects on this page to the count of
allocated memory. */
@@ -1445,12 +1460,12 @@ poison_pages ()
for (order = 2; order < NUM_ORDERS; order++)
{
- size_t num_objects = OBJECTS_PER_PAGE (order);
size_t size = OBJECT_SIZE (order);
page_entry *p;
for (p = G.pages[order]; p != NULL; p = p->next)
{
+ size_t num_objects;
size_t i;
if (p->context_depth != G.context_depth)
@@ -1460,6 +1475,7 @@ poison_pages ()
contexts. */
continue;
+ num_objects = OBJECTS_IN_PAGE (p);
for (i = 0; i < num_objects; i++)
{
size_t word, bit;
@@ -1581,11 +1597,11 @@ ggc_print_statistics ()
for (p = G.pages[i]; p; p = p->next)
{
allocated += p->bytes;
- in_use +=
- (OBJECTS_PER_PAGE (i) - p->num_free_objects) * OBJECT_SIZE (i);
+ in_use +=
+ (OBJECTS_IN_PAGE (p) - p->num_free_objects) * OBJECT_SIZE (i);
overhead += (sizeof (page_entry) - sizeof (long)
- + BITMAP_SIZE (OBJECTS_PER_PAGE (i) + 1));
+ + BITMAP_SIZE (OBJECTS_IN_PAGE (p) + 1));
}
fprintf (stderr, "%-5lu %10lu%c %10lu%c %10lu%c\n",
(unsigned long) OBJECT_SIZE (i),
@@ -1599,3 +1615,225 @@ ggc_print_statistics ()
SCALE (G.allocated), LABEL(G.allocated),
SCALE (total_overhead), LABEL (total_overhead));
}
+
+struct ggc_pch_data
+{
+ struct ggc_pch_ondisk
+ {
+ unsigned totals[NUM_ORDERS];
+ } d;
+ size_t base[NUM_ORDERS];
+ size_t written[NUM_ORDERS];
+};
+
+struct ggc_pch_data *
+init_ggc_pch ()
+{
+ return xcalloc (sizeof (struct ggc_pch_data), 1);
+}
+
+void
+ggc_pch_count_object (d, x, size)
+ struct ggc_pch_data *d;
+ void *x ATTRIBUTE_UNUSED;
+ size_t size;
+{
+ unsigned order;
+
+ if (size <= 256)
+ order = size_lookup[size];
+ else
+ {
+ order = 9;
+ while (size > OBJECT_SIZE (order))
+ order++;
+ }
+
+ d->d.totals[order]++;
+}
+
+size_t
+ggc_pch_total_size (d)
+ struct ggc_pch_data *d;
+{
+ size_t a = 0;
+ unsigned i;
+
+ for (i = 0; i < NUM_ORDERS; i++)
+ a += ROUND_UP (d->d.totals[i] * OBJECT_SIZE (i), G.pagesize);
+ return a;
+}
+
+void
+ggc_pch_this_base (d, base)
+ struct ggc_pch_data *d;
+ void *base;
+{
+ size_t a = (size_t) base;
+ unsigned i;
+
+ for (i = 0; i < NUM_ORDERS; i++)
+ {
+ d->base[i] = a;
+ a += ROUND_UP (d->d.totals[i] * OBJECT_SIZE (i), G.pagesize);
+ }
+}
+
+
+char *
+ggc_pch_alloc_object (d, x, size)
+ struct ggc_pch_data *d;
+ void *x ATTRIBUTE_UNUSED;
+ size_t size;
+{
+ unsigned order;
+ char *result;
+
+ if (size <= 256)
+ order = size_lookup[size];
+ else
+ {
+ order = 9;
+ while (size > OBJECT_SIZE (order))
+ order++;
+ }
+
+ result = (char *) d->base[order];
+ d->base[order] += OBJECT_SIZE (order);
+ return result;
+}
+
+void
+ggc_pch_prepare_write (d, f)
+ struct ggc_pch_data * d ATTRIBUTE_UNUSED;
+ FILE * f ATTRIBUTE_UNUSED;
+{
+ /* Nothing to do. */
+}
+
+void
+ggc_pch_write_object (d, f, x, newx, size)
+ struct ggc_pch_data * d ATTRIBUTE_UNUSED;
+ FILE *f;
+ void *x;
+ void *newx ATTRIBUTE_UNUSED;
+ size_t size;
+{
+ unsigned order;
+
+ if (size <= 256)
+ order = size_lookup[size];
+ else
+ {
+ order = 9;
+ while (size > OBJECT_SIZE (order))
+ order++;
+ }
+
+ if (fwrite (x, size, 1, f) != 1)
+ fatal_io_error ("can't write PCH file");
+
+ /* In the current implementation, SIZE is always equal to
+ OBJECT_SIZE (order) and so the fseek is never executed. */
+ if (size != OBJECT_SIZE (order)
+ && fseek (f, OBJECT_SIZE (order) - size, SEEK_CUR) != 0)
+ fatal_io_error ("can't write PCH file");
+
+ d->written[order]++;
+ if (d->written[order] == d->d.totals[order]
+ && fseek (f, ROUND_UP_VALUE (d->d.totals[order] * OBJECT_SIZE (order),
+ G.pagesize),
+ SEEK_CUR) != 0)
+ fatal_io_error ("can't write PCH file");
+}
+
+void
+ggc_pch_finish (d, f)
+ struct ggc_pch_data * d;
+ FILE *f;
+{
+ if (fwrite (&d->d, sizeof (d->d), 1, f) != 1)
+ fatal_io_error ("can't write PCH file");
+ free (d);
+}
+
+void
+ggc_pch_read (f, addr)
+ FILE *f;
+ void *addr;
+{
+ struct ggc_pch_ondisk d;
+ unsigned i;
+ char *offs = addr;
+
+ /* We've just read in a PCH file. So, every object that used to be allocated
+ is now free. */
+ clear_marks ();
+#ifdef GGC_POISON
+ poison_pages ();
+#endif
+
+ /* No object read from a PCH file should ever be freed. So, set the
+ context depth to 1, and set the depth of all the currently-allocated
+ pages to be 1 too. PCH pages will have depth 0. */
+ if (G.context_depth != 0)
+ abort ();
+ G.context_depth = 1;
+ for (i = 0; i < NUM_ORDERS; i++)
+ {
+ page_entry *p;
+ for (p = G.pages[i]; p != NULL; p = p->next)
+ p->context_depth = G.context_depth;
+ }
+
+ /* Allocate the appropriate page-table entries for the pages read from
+ the PCH file. */
+ if (fread (&d, sizeof (d), 1, f) != 1)
+ fatal_io_error ("can't read PCH file");
+
+ for (i = 0; i < NUM_ORDERS; i++)
+ {
+ struct page_entry *entry;
+ char *pte;
+ size_t bytes;
+ size_t num_objs;
+ size_t j;
+
+ if (d.totals[i] == 0)
+ continue;
+
+ bytes = ROUND_UP (d.totals[i] * OBJECT_SIZE (i), G.pagesize);
+ num_objs = bytes / OBJECT_SIZE (i);
+ entry = xcalloc (1, (sizeof (struct page_entry)
+ - sizeof (long)
+ + BITMAP_SIZE (num_objs + 1)));
+ entry->bytes = bytes;
+ entry->page = offs;
+ entry->context_depth = 0;
+ offs += bytes;
+ entry->num_free_objects = 0;
+ entry->order = i;
+
+ for (j = 0;
+ j + HOST_BITS_PER_LONG <= num_objs + 1;
+ j += HOST_BITS_PER_LONG)
+ entry->in_use_p[j / HOST_BITS_PER_LONG] = -1;
+ for (; j < num_objs + 1; j++)
+ entry->in_use_p[j / HOST_BITS_PER_LONG]
+ |= 1L << (j % HOST_BITS_PER_LONG);
+
+ for (pte = entry->page;
+ pte < entry->page + entry->bytes;
+ pte += G.pagesize)
+ set_page_table_entry (pte, entry);
+
+ if (G.page_tails[i] != NULL)
+ G.page_tails[i]->next = entry;
+ else
+ G.pages[i] = entry;
+ G.page_tails[i] = entry;
+ }
+
+ /* Update the statistics. */
+ G.allocated = G.allocated_last_gc = offs - (char *)addr;
+}
diff --git a/gcc/ggc-simple.c b/gcc/ggc-simple.c
index 554ef722669..65bc1b64839 100644
--- a/gcc/ggc-simple.c
+++ b/gcc/ggc-simple.c
@@ -1,5 +1,5 @@
/* Simple garbage collection for the GNU compiler.
- Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
@@ -28,6 +28,7 @@
#include "flags.h"
#include "varray.h"
#include "ggc.h"
+#include "toplev.h"
#include "timevar.h"
#include "params.h"
@@ -490,16 +491,90 @@ ggc_print_statistics ()
fprintf (stderr, "\n\
Total internal data (bytes)\t%ld%c\n\
-Number of leaves in tree\t%d\n\
+Number of leaves in tree\t%lu\n\
Average leaf depth\t\t%.1f\n",
SCALE(G.objects * offsetof (struct ggc_mem, u)),
LABEL(G.objects * offsetof (struct ggc_mem, u)),
- nleaf, (double)sumdepth / (double)nleaf);
+ (unsigned long)nleaf, (double)sumdepth / (double)nleaf);
/* Report overall memory usage. */
fprintf (stderr, "\n\
-Total objects allocated\t\t%d\n\
+Total objects allocated\t\t%ld\n\
Total memory in GC arena\t%ld%c\n",
- G.objects,
+ (unsigned long)G.objects,
SCALE(G.allocated), LABEL(G.allocated));
}
+
+struct ggc_pch_data *
+init_ggc_pch ()
+{
+ sorry ("Generating PCH files is not supported when using ggc-simple.c");
+ /* It could be supported, but the code is not yet written. */
+ return NULL;
+}
+
+void
+ggc_pch_count_object (d, x, size)
+ struct ggc_pch_data *d ATTRIBUTE_UNUSED;
+ void *x ATTRIBUTE_UNUSED;
+ size_t size ATTRIBUTE_UNUSED;
+{
+}
+
+size_t
+ggc_pch_total_size (d)
+ struct ggc_pch_data *d ATTRIBUTE_UNUSED;
+{
+ return 0;
+}
+
+void
+ggc_pch_this_base (d, base)
+ struct ggc_pch_data *d ATTRIBUTE_UNUSED;
+ void *base ATTRIBUTE_UNUSED;
+{
+}
+
+
+char *
+ggc_pch_alloc_object (d, x, size)
+ struct ggc_pch_data *d ATTRIBUTE_UNUSED;
+ void *x ATTRIBUTE_UNUSED;
+ size_t size ATTRIBUTE_UNUSED;
+{
+ return NULL;
+}
+
+void
+ggc_pch_prepare_write (d, f)
+ struct ggc_pch_data * d ATTRIBUTE_UNUSED;
+ FILE * f ATTRIBUTE_UNUSED;
+{
+}
+
+void
+ggc_pch_write_object (d, f, x, newx, size)
+ struct ggc_pch_data * d ATTRIBUTE_UNUSED;
+ FILE *f ATTRIBUTE_UNUSED;
+ void *x ATTRIBUTE_UNUSED;
+ void *newx ATTRIBUTE_UNUSED;
+ size_t size ATTRIBUTE_UNUSED;
+{
+}
+
+void
+ggc_pch_finish (d, f)
+ struct ggc_pch_data * d ATTRIBUTE_UNUSED;
+ FILE *f ATTRIBUTE_UNUSED;
+{
+}
+
+void
+ggc_pch_read (f, addr)
+ FILE *f ATTRIBUTE_UNUSED;
+ void *addr ATTRIBUTE_UNUSED;
+{
+ /* This should be impossible, since we won't generate any valid PCH
+ files for this configuration. */
+ abort ();
+}
diff --git a/gcc/ggc.h b/gcc/ggc.h
index 4cd6242ee92..86ae60a7d99 100644
--- a/gcc/ggc.h
+++ b/gcc/ggc.h
@@ -18,9 +18,6 @@ along with GCC; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
-#include "varray.h"
-#include "gtype-desc.h"
-
/* Symbols are marked with `ggc' for `gcc gc' so as not to interfere with
an external gc library that might be linked in. */
@@ -29,10 +26,39 @@ extern const char empty_string[]; /* empty string */
extern const char digit_vector[]; /* "0" .. "9" */
#define digit_string(d) (digit_vector + ((d) * 2))
-/* Manipulate global roots that are needed between calls to gc.
- THIS ROUTINE IS OBSOLETE, do not use it for new code. */
-extern void ggc_add_root PARAMS ((void *base, int nelt,
- int size, void (*)(void *)));
+/* Internal functions and data structures used by the GTY
+ machinery. */
+
+/* The first parameter is a pointer to a pointer, the second a cookie. */
+typedef void (*gt_pointer_operator) PARAMS ((void *, void *));
+
+#include "gtype-desc.h"
+
+/* One of these applies its third parameter (with cookie in the fourth
+ parameter) to each pointer in the object pointed to by the first
+ parameter, using the second parameter. */
+typedef void (*gt_note_pointers)
+ PARAMS ((void *, void *, gt_pointer_operator, void *));
+
+/* One of these is called before objects are re-ordered in memory.
+ The first parameter is the original object, the second is the
+ subobject that has had its pointers reordered, the third parameter
+ can compute the new values of a pointer when given the cookie in
+ the fourth parameter. */
+typedef void (*gt_handle_reorder)
+ PARAMS ((void *, void *, gt_pointer_operator, void *));
+
+/* Used by the gt_pch_n_* routines. Register an object in the hash table. */
+extern int gt_pch_note_object
+ PARAMS ((void *, void *, gt_note_pointers));
+
+/* Used by the gt_pch_n_* routines. Register that an object has a reorder
+ function. */
+extern void gt_pch_note_reorder
+ PARAMS ((void *, void *, gt_handle_reorder));
+
+/* Mark the object in the first parameter and anything it points to. */
+typedef void (*gt_pointer_walker) PARAMS ((void *));
/* Structures for the easy way to mark roots.
In an array, terminated by having base == NULL.*/
@@ -40,12 +66,15 @@ struct ggc_root_tab {
void *base;
size_t nelt;
size_t stride;
- void (*cb) PARAMS ((void *));
+ gt_pointer_walker cb;
+ gt_pointer_walker pchw;
};
-#define LAST_GGC_ROOT_TAB { NULL, 0, 0, NULL }
+#define LAST_GGC_ROOT_TAB { NULL, 0, 0, NULL, NULL }
/* Pointers to arrays of ggc_root_tab, terminated by NULL. */
extern const struct ggc_root_tab * const gt_ggc_rtab[];
extern const struct ggc_root_tab * const gt_ggc_deletable_rtab[];
+extern const struct ggc_root_tab * const gt_pch_cache_rtab[];
+extern const struct ggc_root_tab * const gt_pch_scalar_rtab[];
/* Structure for hash table cache marking. */
struct htab;
@@ -53,23 +82,19 @@ struct ggc_cache_tab {
struct htab * *base;
size_t nelt;
size_t stride;
- void (*cb) PARAMS ((void *));
+ gt_pointer_walker cb;
+ gt_pointer_walker pchw;
int (*marked_p) PARAMS ((const void *));
};
-#define LAST_GGC_CACHE_TAB { NULL, 0, 0, NULL, NULL }
+#define LAST_GGC_CACHE_TAB { NULL, 0, 0, NULL, NULL, NULL }
/* Pointers to arrays of ggc_cache_tab, terminated by NULL. */
extern const struct ggc_cache_tab * const gt_ggc_cache_rtab[];
-extern void ggc_mark_roots PARAMS ((void));
-
/* If EXPR is not NULL and previously unmarked, mark it and evaluate
to true. Otherwise evaluate to false. */
#define ggc_test_and_set_mark(EXPR) \
((EXPR) != NULL && ((void *) (EXPR)) != (void *) 1 && ! ggc_set_mark (EXPR))
-#define ggc_mark_rtx gt_ggc_m_7rtx_def
-#define ggc_mark_tree gt_ggc_m_9tree_node
-
#define ggc_mark(EXPR) \
do { \
const void *const a__ = (EXPR); \
@@ -77,11 +102,45 @@ extern void ggc_mark_roots PARAMS ((void));
ggc_set_mark (a__); \
} while (0)
-/* A GC implementation must provide these functions. */
+/* Actually set the mark on a particular region of memory, but don't
+ follow pointers. This function is called by ggc_mark_*. It
+ returns zero if the object was not previously marked; non-zero if
+ the object was already marked, or if, for any other reason,
+ pointers in this data structure should not be traversed. */
+extern int ggc_set_mark PARAMS ((const void *));
+
+/* Return 1 if P has been marked, zero otherwise.
+ P must have been allocated by the GC allocator; it mustn't point to
+ static objects, stack variables, or memory allocated with malloc. */
+extern int ggc_marked_p PARAMS ((const void *));
+
+/* Mark the entries in the string pool. */
+extern void ggc_mark_stringpool PARAMS ((void));
+
+/* Call ggc_set_mark on all the roots. */
+
+extern void ggc_mark_roots PARAMS ((void));
+
+/* Save and restore the string pool entries for PCH. */
+
+extern void gt_pch_save_stringpool PARAMS ((void));
+extern void gt_pch_restore_stringpool PARAMS ((void));
+
+/* PCH and GGC handling for strings, mostly trivial. */
+
+extern void gt_pch_p_S PARAMS ((void *, void *,
+ gt_pointer_operator, void *));
+extern void gt_pch_n_S PARAMS ((const void *));
+extern void gt_ggc_m_S PARAMS ((void *));
+
+/* Initialise the string pool. */
+extern void init_stringpool PARAMS ((void));
+
+/* A GC implementation must provide these functions. They are internal
+ to the GC system. */
/* 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. */
@@ -91,6 +150,48 @@ extern void ggc_push_context PARAMS ((void));
will be merged with the old context. */
extern void ggc_pop_context PARAMS ((void));
+struct ggc_pch_data;
+
+/* Return a new ggc_pch_data structure. */
+extern struct ggc_pch_data *init_ggc_pch PARAMS ((void));
+
+/* The second parameter and third parameters give the address and size
+ of an object. Update the ggc_pch_data structure with as much of
+ that information as is necessary. */
+extern void ggc_pch_count_object PARAMS ((struct ggc_pch_data *,
+ void *, size_t));
+
+/* Return the total size of the data to be written to hold all
+ the objects previously passed to ggc_pch_count_object. */
+extern size_t ggc_pch_total_size PARAMS ((struct ggc_pch_data *));
+
+/* The objects, when read, will most likely be at the address
+ in the second parameter. */
+extern void ggc_pch_this_base PARAMS ((struct ggc_pch_data *,
+ void *));
+
+/* Assuming that the objects really do end up at the address
+ passed to ggc_pch_this_base, return the address of this object. */
+extern char *ggc_pch_alloc_object PARAMS ((struct ggc_pch_data *,
+ void *, size_t));
+
+/* Write out any initial information required. */
+extern void ggc_pch_prepare_write PARAMS ((struct ggc_pch_data *,
+ FILE *));
+/* Write out this object, including any padding. */
+extern void ggc_pch_write_object PARAMS ((struct ggc_pch_data *,
+ FILE *, void *, void *,
+ size_t));
+/* All objects have been written, write out any final information
+ required. */
+extern void ggc_pch_finish PARAMS ((struct ggc_pch_data *,
+ FILE *));
+
+/* A PCH file has just been read in at the address specified second
+ parameter. Set up the GC implementation for the new objects. */
+extern void ggc_pch_read PARAMS ((FILE *, void *));
+
+
/* Allocation. */
/* The internal primitive. */
@@ -115,6 +216,13 @@ extern void *ggc_calloc PARAMS ((size_t, size_t));
#define htab_create_ggc(SIZE, HASH, EQ, DEL) \
htab_create_alloc (SIZE, HASH, EQ, DEL, ggc_calloc, NULL)
+#define splay_tree_new_ggc(COMPARE) \
+ splay_tree_new_with_allocator (COMPARE, NULL, NULL, \
+ &ggc_splay_alloc, &ggc_splay_dont_free, \
+ NULL)
+extern PTR ggc_splay_alloc PARAMS ((int, void *));
+extern void ggc_splay_dont_free PARAMS ((void *, void *));
+
/* 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. */
@@ -128,47 +236,25 @@ extern const char *ggc_alloc_string PARAMS ((const char *contents,
function is called, not during allocations. */
extern void ggc_collect PARAMS ((void));
-/* Actually set the mark on a particular region of memory, but don't
- follow pointers. This function is called by ggc_mark_*. It
- returns zero if the object was not previously marked; nonzero if
- the object was already marked, or if, for any other reason,
- pointers in this data structure should not be traversed. */
-extern int ggc_set_mark PARAMS ((const void *));
+/* Return the number of bytes allocated at the indicated address. */
+extern size_t ggc_get_size PARAMS ((const void *));
-/* Return 1 if P has been marked, zero otherwise.
- P must have been allocated by the GC allocator; it mustn't point to
- static objects, stack variables, or memory allocated with malloc. */
-extern int ggc_marked_p PARAMS ((const void *));
+/* Write out all GCed objects to F. */
+extern void gt_pch_save PARAMS ((FILE *f));
+/* Read objects previously saved with gt_pch_save from F. */
+extern void gt_pch_restore PARAMS ((FILE *f));
+
/* Statistics. */
/* This structure contains the statistics common to all collectors.
Particular collectors can extend this structure. */
typedef struct ggc_statistics
{
- /* The Ith element is the number of nodes allocated with code I. */
- unsigned num_trees[256];
- /* The Ith element is the number of bytes allocated by nodes with
- code I. */
- size_t size_trees[256];
- /* The Ith element is the number of nodes allocated with code I. */
- unsigned num_rtxs[256];
- /* The Ith element is the number of bytes allocated by nodes with
- code I. */
- size_t size_rtxs[256];
- /* The total size of the tree nodes allocated. */
- size_t total_size_trees;
- /* The total size of the RTL nodes allocated. */
- size_t total_size_rtxs;
- /* The total number of tree nodes allocated. */
- unsigned total_num_trees;
- /* The total number of RTL nodes allocated. */
- unsigned total_num_rtxs;
+ /* At present, we don't really gather any interesting statistics. */
+ int unused;
} ggc_statistics;
-/* Return the number of bytes allocated at the indicated address. */
-extern size_t ggc_get_size PARAMS ((const void *));
-
/* Used by the various collectors to gather and print statistics that
do not depend on the collector in use. */
extern void ggc_print_common_statistics PARAMS ((FILE *, ggc_statistics *));
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index 34d39a45214..00b5e50a9fb 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -1,3 +1,77 @@
+2003-01-09 Geoffrey Keating <geoffk@apple.com>
+
+ Merge from pch-branch:
+
+ 2002-12-02 Geoffrey Keating <geoffk@apple.com>
+
+ * Make-lang.in (java/gjavah.o): Update dependencies.
+ * gjavah.c: Include ggc.h.
+
+ 2002-08-16 Geoffrey Keating <geoffk@redhat.com>
+
+ * Make-lang.in (GCJH_OBJS): Add ggc-none.o.
+ (JCFDUMP_OBJS): Add ggc-none.o.
+ (java/jcf-dump.o): Depend on GGC_H.
+ * jcf-reader.c (jcf_parse_constant_pool): Use ggc_alloc to allocate
+ CPool substructures.
+ * jcf-parse.c (process_zip_dir): Use ggc_alloc to allocate JCFs.
+ * jcf-dump.c: Include ggc.h.
+
+ 2002-08-08 Geoffrey Keating <geoffk@redhat.com>
+
+ * jcf.h (union cpool_entry): New.
+ (struct CPool): Use gengtype to mark. Change field 'data' to be
+ an array of unions.
+ (struct JCF): Use gengtype to mark.
+ (CPOOL_UINT): Update for new cpool_entry type.
+ (CPOOL_USHORT1): Likewise.
+ (CPOOL_USHORT2): Likewise.
+ (CPOOL_FINISH): Use GC to free cpool subfields.
+ * parse.h (struct parser_ctxt): Mark field current_jcf.
+ * lex.c (java_init_lex): Use GC to allocate struct JCF.
+ * jcf-parse.c (HANDLE_CONSTANT_Utf8): Update for new cpool_entry type.
+ (main_jcf): Use gengtype to mark.
+ (ggc_mark_jcf): Delete.
+ (get_constant): Update for new cpool_entry type.
+ (give_name_to_class): Likewise.
+ (get_class_constant): Likewise.
+ (init_outgoing_cpool): Use GGC to allocate struct CPool.
+ (java_parse_file): Use GGC to allocate struct JCF.
+ (init_jcf_parse): Don't call ggc_add_root.
+ * jcf-reader.c (jcf_parse_constant_pool): Update for new
+ cpool_entry type.
+ * java-tree.h (current_jcf): Use gengtype to mark.
+ (CPOOL_UTF): Update for new cpool_entry type.
+ (outgoing_cpool): Use gengtype to mark.
+ (struct lang_type): GC struct JCF and struct CPool.
+ * config-lang.in (gtfiles): Add jcf.h.
+ * constants.c (find_tree_constant): New.
+ (set_constant_entry): Allocate cpool subfields using GGC. Update
+ for new cpool_entry type.
+ (find_constant1): Update for new cpool_entry type.
+ (find_constant2): Likewise.
+ (find_utf8_constant): Use find_tree_constant.
+ (find_class_or_string_constant): Remove unnecessary cast to jword.
+ Update for new cpool_entry type.
+ (count_constant_pool_bytes): Update for new cpool_entry type.
+ (write_constant_pool): Likewise.
+ (alloc_name_constant): Use find_tree_constant.
+ (build_constants_constructor): Update for new cpool_entry type.
+
+ 2002-08-08 Geoffrey Keating <geoffk@redhat.com>
+
+ * parse.y (mark_parser_ctxt): Delete.
+ (goal): Don't use ggc_add_root.
+ (create_new_parser_context): Use GC to allocate struct parser_ctxt.
+ (java_pop_parser_context): Let GC free parser_ctxt.
+ (java_parser_context_resume): Likewise.
+ * parse.h (struct parser_ctxt): Use gengtype to mark.
+ (ctxp): Likewise.
+ (ctxp_for_generation): Likewise.
+ * lex.h (struct java_lc_s): Mark for gengtype.
+ (java_lexer): Rearrange for gengtype.
+ * config-lang.in (gtfiles): Add lex.h, parse.h.
+
2003-01-09 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* All Files: Remove PARAMS macro.
diff --git a/gcc/java/Make-lang.in b/gcc/java/Make-lang.in
index b04a975630e..bd839d6a354 100644
--- a/gcc/java/Make-lang.in
+++ b/gcc/java/Make-lang.in
@@ -113,12 +113,12 @@ JAVA_OBJS = java/parse.o java/class.o java/decl.o java/expr.o \
java/jcf-path.o java/xref.o java/boehm.o java/java-tree-inline.o mkdeps.o
GCJH_OBJS = java/gjavah.o java/jcf-io.o java/jcf-depend.o java/jcf-path.o \
- java/zextract.o version.o mkdeps.o errors.o
+ java/zextract.o version.o mkdeps.o errors.o ggc-none.o
JVSCAN_OBJS = java/parse-scan.o java/jv-scan.o version.o
JCFDUMP_OBJS = java/jcf-dump.o java/jcf-io.o java/jcf-depend.o java/jcf-path.o \
- java/zextract.o errors.o version.o mkdeps.o
+ java/zextract.o errors.o version.o mkdeps.o ggc-none.o
JVGENMAIN_OBJS = java/jvgenmain.o java/mangle_name.o errors.o
@@ -267,9 +267,9 @@ java/parse.o: java/parse.c java/jcf-reader.c $(CONFIG_H) $(SYSTEM_H) \
java/lex.h $(GGC_H) debug.h gt-java-parse.h gtype-java.h
java/jcf-dump.o: $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(JAVA_TREE_H) \
java/jcf-dump.c java/jcf-reader.c java/jcf.h java/javaop.h java/javaop.def \
- version.h
+ version.h $(GGC_H)
java/gjavah.o: $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(JAVA_TREE_H) \
- java/gjavah.c java/jcf-reader.c java/jcf.h java/javaop.h version.h
+ java/gjavah.c java/jcf-reader.c java/jcf.h java/javaop.h version.h $(GGC_H)
java/boehm.o: java/boehm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) $(JAVA_TREE_H) java/parse.h toplev.h
java/buffer.o: java/buffer.c $(CONFIG_H) java/buffer.h $(SYSTEM_H) coretypes.h \
diff --git a/gcc/java/config-lang.in b/gcc/java/config-lang.in
index 993763ed500..05a6fdff7e7 100644
--- a/gcc/java/config-lang.in
+++ b/gcc/java/config-lang.in
@@ -36,7 +36,7 @@ compilers="jc1\$(exeext) jvgenmain\$(exeext)"
stagestuff="jc1\$(exeext) gcj\$(exeext) jvgenmain\$(exeext) gcjh\$(exeext) jv-scan\$(exeext) jcf-dump\$(exeext)"
-gtfiles="\$(srcdir)/java/java-tree.h \$(srcdir)/java/builtins.c \$(srcdir)/java/class.c \$(srcdir)/java/constants.c \$(srcdir)/java/decl.c \$(srcdir)/java/expr.c \$(srcdir)/java/jcf-parse.c \$(srcdir)/java/jcf-write.c \$(srcdir)/java/lang.c \$(srcdir)/java/mangle.c \$(srcdir)/java/parse.y"
+gtfiles="\$(srcdir)/java/java-tree.h \$(srcdir)/java/jcf.h \$(srcdir)/java/lex.h \$(srcdir)/java/parse.h \$(srcdir)/java/builtins.c \$(srcdir)/java/class.c \$(srcdir)/java/constants.c \$(srcdir)/java/decl.c \$(srcdir)/java/expr.c \$(srcdir)/java/jcf-parse.c \$(srcdir)/java/jcf-write.c \$(srcdir)/java/lang.c \$(srcdir)/java/mangle.c \$(srcdir)/java/parse.y"
target_libs=${libgcj_saved}
lang_dirs="zlib fastjar"
diff --git a/gcc/java/constants.c b/gcc/java/constants.c
index 11efc2bf0c0..a1872387f18 100644
--- a/gcc/java/constants.c
+++ b/gcc/java/constants.c
@@ -32,6 +32,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */
#include "ggc.h"
static void set_constant_entry (CPool *, int, int, jword);
+static int find_tree_constant (CPool *, int, tree);
static int find_class_or_string_constant (CPool *, int, tree);
static int find_name_and_type_constant (CPool *, tree, tree);
static tree get_tag_node (int);
@@ -49,8 +50,8 @@ set_constant_entry (cpool, index, tag, value)
if (cpool->data == NULL)
{
cpool->capacity = 100;
- cpool->tags = xmalloc (sizeof(uint8) * cpool->capacity);
- cpool->data = xmalloc (sizeof(jword) * cpool->capacity);
+ cpool->tags = ggc_alloc (sizeof(uint8) * cpool->capacity);
+ cpool->data = ggc_alloc (sizeof(union cpool_entry) * cpool->capacity);
cpool->count = 1;
}
if (index >= cpool->capacity)
@@ -58,13 +59,15 @@ set_constant_entry (cpool, index, tag, value)
cpool->capacity *= 2;
if (index >= cpool->capacity)
cpool->capacity = index + 10;
- cpool->tags = xrealloc (cpool->tags, sizeof(uint8) * cpool->capacity);
- cpool->data = xrealloc (cpool->data, sizeof(jword) * cpool->capacity);
+ cpool->tags = ggc_realloc (cpool->tags,
+ sizeof(uint8) * cpool->capacity);
+ cpool->data = ggc_realloc (cpool->data,
+ sizeof(union cpool_entry) * cpool->capacity);
}
if (index >= cpool->count)
cpool->count = index + 1;
cpool->tags[index] = tag;
- cpool->data[index] = value;
+ cpool->data[index].w = value;
}
/* Find (or create) a constant pool entry matching TAG and VALUE. */
@@ -78,7 +81,7 @@ find_constant1 (cpool, tag, value)
int i;
for (i = cpool->count; --i > 0; )
{
- if (cpool->tags[i] == tag && cpool->data[i] == value)
+ if (cpool->tags[i] == tag && cpool->data[i].w == value)
return i;
}
i = cpool->count == 0 ? 1 : cpool->count;
@@ -98,8 +101,8 @@ find_constant2 (cpool, tag, word1, word2)
for (i = cpool->count - 1; --i > 0; )
{
if (cpool->tags[i] == tag
- && cpool->data[i] == word1
- && cpool->data[i+1] == word2)
+ && cpool->data[i].w == word1
+ && cpool->data[i+1].w == word2)
return i;
}
i = cpool->count == 0 ? 1 : cpool->count;
@@ -108,6 +111,25 @@ find_constant2 (cpool, tag, word1, word2)
return i;
}
+static int
+find_tree_constant (cpool, tag, value)
+ CPool *cpool;
+ int tag;
+ tree value;
+{
+ int i;
+ for (i = cpool->count; --i > 0; )
+ {
+ if (cpool->tags[i] == tag && cpool->data[i].t == value)
+ return i;
+ }
+ i = cpool->count == 0 ? 1 : cpool->count;
+ set_constant_entry (cpool, i, tag, 0);
+ cpool->data[i].t = value;
+ return i;
+}
+
+
int
find_utf8_constant (cpool, name)
CPool *cpool;
@@ -115,7 +137,7 @@ find_utf8_constant (cpool, name)
{
if (name == NULL_TREE)
return 0;
- return find_constant1 (cpool, CONSTANT_Utf8, (jword) name);
+ return find_tree_constant (cpool, CONSTANT_Utf8, name);
}
static int
@@ -124,15 +146,15 @@ find_class_or_string_constant (cpool, tag, name)
int tag;
tree name;
{
- int j = find_utf8_constant (cpool, name);
+ jword j = find_utf8_constant (cpool, name);
int i;
for (i = cpool->count; --i > 0; )
{
- if (cpool->tags[i] == tag && cpool->data[i] == (jword) j)
+ if (cpool->tags[i] == tag && cpool->data[i].w == j)
return i;
}
i = cpool->count;
- set_constant_entry (cpool, i, tag, (jword) j);
+ set_constant_entry (cpool, i, tag, j);
return i;
}
@@ -255,7 +277,7 @@ count_constant_pool_bytes (cpool)
break;
case CONSTANT_Utf8:
{
- tree t = (tree) cpool->data[i];
+ tree t = cpool->data[i].t;
int len = IDENTIFIER_LENGTH (t);
size += len + 2;
}
@@ -279,7 +301,7 @@ write_constant_pool (cpool, buffer, length)
{
unsigned char *ptr = buffer;
int i = 1;
- jword *datap = &cpool->data[1];
+ union cpool_entry *datap = &cpool->data[1];
PUT2 (cpool->count);
for ( ; i < cpool->count; i++, datap++)
{
@@ -293,23 +315,23 @@ write_constant_pool (cpool, buffer, length)
case CONSTANT_InterfaceMethodref:
case CONSTANT_Float:
case CONSTANT_Integer:
- PUT4 (*datap);
+ PUT4 (datap->w);
break;
case CONSTANT_Class:
case CONSTANT_String:
- PUT2 (*datap);
+ PUT2 (datap->w);
break;
break;
case CONSTANT_Long:
case CONSTANT_Double:
- PUT4(*datap);
+ PUT4(datap->w);
i++;
datap++;
- PUT4 (*datap);
+ PUT4 (datap->w);
break;
case CONSTANT_Utf8:
{
- tree t = (tree) *datap;
+ tree t = datap->t;
int len = IDENTIFIER_LENGTH (t);
PUT2 (len);
PUTN (IDENTIFIER_POINTER (t), len);
@@ -347,7 +369,7 @@ alloc_name_constant (tag, name)
int tag;
tree name;
{
- return find_constant1 (outgoing_cpool, tag, (jword) name);
+ return find_tree_constant (outgoing_cpool, tag, name);
}
/* Build an identifier for the internal name of reference type TYPE. */
@@ -438,7 +460,7 @@ build_constants_constructor ()
= tree_cons (NULL_TREE, get_tag_node (outgoing_cpool->tags[i]),
tags_list);
data_list
- = tree_cons (NULL_TREE, build_utf8_ref ((tree)outgoing_cpool->data[i]),
+ = tree_cons (NULL_TREE, build_utf8_ref (outgoing_cpool->data[i].t),
data_list);
}
if (outgoing_cpool->count > 0)
diff --git a/gcc/java/gjavah.c b/gcc/java/gjavah.c
index 45509977cde..0c333137c56 100644
--- a/gcc/java/gjavah.c
+++ b/gcc/java/gjavah.c
@@ -38,6 +38,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */
#include "javaop.h"
#include "java-tree.h"
#include "java-opcodes.h"
+#include "ggc.h"
#include "hashtab.h"
#include <getopt.h>
diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h
index b4ed394eec7..9a79f3e36b4 100644
--- a/gcc/java/java-tree.h
+++ b/gcc/java/java-tree.h
@@ -229,7 +229,7 @@ extern int flag_store_check;
extern const char *current_encoding;
/* The Java .class file that provides main_class; the main input file. */
-extern struct JCF *current_jcf;
+extern GTY(()) struct JCF * current_jcf;
typedef struct CPool constant_pool;
@@ -241,7 +241,7 @@ typedef struct CPool constant_pool;
/* The cpool->data[i] for a ResolvedClass points to a RECORD_TYPE. */
#define CONSTANT_ResolvedClass (CONSTANT_Class+CONSTANT_ResolvedFlag)
-#define CPOOL_UTF(CPOOL, INDEX) ((tree) (CPOOL)->data[INDEX])
+#define CPOOL_UTF(CPOOL, INDEX) ((CPOOL)->data[INDEX].t)
/* A NameAndType constant is represented as a TREE_LIST.
The type is the signature string (as an IDENTIFIER_NODE). */
@@ -686,7 +686,7 @@ extern GTY(()) tree java_global_trees[JTI_MAX];
#define nativecode_ptr_type_node ptr_type_node
/* They need to be reset before processing each class */
-extern struct CPool *outgoing_cpool;
+extern GTY(()) struct CPool *outgoing_cpool;
#define wfl_operator \
java_global_trees[JTI_WFL_OPERATOR]
@@ -1066,8 +1066,8 @@ struct lang_decl GTY(())
struct lang_type GTY(())
{
tree signature;
- struct JCF * GTY ((skip (""))) jcf;
- struct CPool * GTY ((skip (""))) cpool;
+ struct JCF * jcf;
+ struct CPool * cpool;
tree cpool_data_ref; /* Cached */
tree finit_stmt_list; /* List of statements finit$ will use */
tree clinit_stmt_list; /* List of statements <clinit> will use */
diff --git a/gcc/java/jcf-dump.c b/gcc/java/jcf-dump.c
index e780b8430bf..a5de5c57cb5 100644
--- a/gcc/java/jcf-dump.c
+++ b/gcc/java/jcf-dump.c
@@ -53,6 +53,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */
#include "system.h"
#include "coretypes.h"
#include "tm.h"
+#include "ggc.h"
#include "jcf.h"
#include "tree.h"
diff --git a/gcc/java/jcf-parse.c b/gcc/java/jcf-parse.c
index 93798261b3a..cd2c1cf819f 100644
--- a/gcc/java/jcf-parse.c
+++ b/gcc/java/jcf-parse.c
@@ -62,7 +62,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */
text = (JCF)->read_ptr; \
save = text[LENGTH]; \
text[LENGTH] = 0; \
- (JCF)->cpool.data[INDEX] = (jword) get_identifier (text); \
+ (JCF)->cpool.data[INDEX].t = get_identifier (text); \
text[LENGTH] = save; \
JCF_SKIP (JCF, LENGTH); } while (0)
@@ -86,7 +86,7 @@ static GTY(()) tree parse_roots[3];
#define current_file_list parse_roots[2]
/* The Java archive that provides main_class; the main input file. */
-static struct JCF main_jcf[1];
+static GTY(()) struct JCF * main_jcf;
static struct ZipFile *localToFile;
@@ -100,33 +100,9 @@ static void parse_source_file_2 (void);
static void parse_source_file_3 (void);
static void parse_class_file (void);
static void set_source_filename (JCF *, int);
-static void ggc_mark_jcf (void**);
static void jcf_parse (struct JCF*);
static void load_inner_classes (tree);
-/* Mark (for garbage collection) all the tree nodes that are
- referenced from JCF's constant pool table. Do that only if the JCF
- hasn't been marked finished. */
-
-static void
-ggc_mark_jcf (elt)
- void **elt;
-{
- JCF *jcf = *(JCF**) elt;
- if (jcf != NULL && !jcf->finished)
- {
- CPool *cpool = &jcf->cpool;
- int size = CPOOL_COUNT(cpool);
- int index;
- for (index = 1; index < size; index++)
- {
- int tag = JPOOL_TAG (jcf, index);
- if ((tag & CONSTANT_ResolvedFlag) || tag == CONSTANT_Utf8)
- ggc_mark_tree ((tree) cpool->data[index]);
- }
- }
-}
-
/* Handle "SourceFile" attribute. */
static void
@@ -270,7 +246,7 @@ get_constant (jcf, index)
goto bad;
tag = JPOOL_TAG (jcf, index);
if ((tag & CONSTANT_ResolvedFlag) || tag == CONSTANT_Utf8)
- return (tree) jcf->cpool.data[index];
+ return jcf->cpool.data[index].t;
switch (tag)
{
case CONSTANT_Integer:
@@ -352,7 +328,7 @@ get_constant (jcf, index)
goto bad;
}
JPOOL_TAG (jcf, index) = tag | CONSTANT_ResolvedFlag;
- jcf->cpool.data [index] = (jword) value;
+ jcf->cpool.data[index].t = value;
return value;
bad:
internal_error ("bad value constant type %d, index %d",
@@ -435,7 +411,7 @@ give_name_to_class (jcf, i)
if (main_input_filename == NULL && jcf == main_jcf)
main_input_filename = input_filename;
- jcf->cpool.data[i] = (jword) this_class;
+ jcf->cpool.data[i].t = this_class;
JPOOL_TAG (jcf, i) = CONSTANT_ResolvedClass;
return this_class;
}
@@ -465,11 +441,11 @@ get_class_constant (JCF *jcf , int i)
tree cname = unmangle_classname (name, nlength);
type = lookup_class (cname);
}
- jcf->cpool.data[i] = (jword) type;
+ jcf->cpool.data[i].t = type;
JPOOL_TAG (jcf, i) = CONSTANT_ResolvedClass;
}
else
- type = (tree) jcf->cpool.data[i];
+ type = jcf->cpool.data[i].t;
return type;
}
@@ -709,8 +685,7 @@ load_inner_classes (cur_class)
void
init_outgoing_cpool ()
{
- outgoing_cpool = xmalloc (sizeof (struct CPool));
- memset (outgoing_cpool, 0, sizeof (struct CPool));
+ outgoing_cpool = ggc_alloc_cleared (sizeof (struct CPool));
}
static void
@@ -1074,7 +1049,7 @@ java_parse_file (set_yydebug)
if (magic == 0xcafebabe)
{
CLASS_FILE_P (node) = 1;
- current_jcf = ALLOC (sizeof (JCF));
+ current_jcf = ggc_alloc (sizeof (JCF));
JCF_ZERO (current_jcf);
current_jcf->read_state = finput;
current_jcf->filbuf = jcf_filbuf_from_stdio;
@@ -1086,6 +1061,7 @@ java_parse_file (set_yydebug)
else if (magic == (JCF_u4)ZIPMAGIC)
{
ZIP_FILE_P (node) = 1;
+ main_jcf = ggc_alloc (sizeof (JCF));
JCF_ZERO (main_jcf);
main_jcf->read_state = finput;
main_jcf->filbuf = jcf_filbuf_from_stdio;
@@ -1223,7 +1199,7 @@ process_zip_dir (FILE *finput)
class_name = ALLOC (zdir->filename_length+1-6);
file_name = ALLOC (zdir->filename_length+1);
- jcf = ALLOC (sizeof (JCF));
+ jcf = ggc_alloc (sizeof (JCF));
JCF_ZERO (jcf);
strncpy (class_name, class_name_in_zip_dir, zdir->filename_length-6);
@@ -1255,9 +1231,6 @@ process_zip_dir (FILE *finput)
void
init_jcf_parse ()
{
- /* Register roots with the garbage collector. */
- ggc_add_root (&current_jcf, 1, sizeof (JCF), (void (*)(void *))ggc_mark_jcf);
-
init_src_parse ();
}
diff --git a/gcc/java/jcf-reader.c b/gcc/java/jcf-reader.c
index 1bd5299e97a..da45cc92ee6 100644
--- a/gcc/java/jcf-reader.c
+++ b/gcc/java/jcf-reader.c
@@ -264,8 +264,8 @@ jcf_parse_constant_pool (JCF* jcf)
{
int i, n;
JPOOL_SIZE (jcf) = (JCF_FILL (jcf, 2), JCF_readu2 (jcf));
- jcf->cpool.tags = ALLOC (JPOOL_SIZE (jcf));
- jcf->cpool.data = ALLOC (sizeof (jword) * JPOOL_SIZE (jcf));
+ jcf->cpool.tags = ggc_alloc (JPOOL_SIZE (jcf));
+ jcf->cpool.data = ggc_alloc (sizeof (jword) * JPOOL_SIZE (jcf));
jcf->cpool.tags[0] = 0;
#ifdef HANDLE_START_CONSTANT_POOL
HANDLE_START_CONSTANT_POOL (JPOOL_SIZE (jcf));
@@ -285,25 +285,25 @@ jcf_parse_constant_pool (JCF* jcf)
{
case CONSTANT_String:
case CONSTANT_Class:
- jcf->cpool.data[i] = JCF_readu2 (jcf);
+ jcf->cpool.data[i].w = JCF_readu2 (jcf);
break;
case CONSTANT_Fieldref:
case CONSTANT_Methodref:
case CONSTANT_InterfaceMethodref:
case CONSTANT_NameAndType:
- jcf->cpool.data[i] = JCF_readu2 (jcf);
- jcf->cpool.data[i] |= JCF_readu2 (jcf) << 16;
+ jcf->cpool.data[i].w = JCF_readu2 (jcf);
+ jcf->cpool.data[i].w |= JCF_readu2 (jcf) << 16;
break;
case CONSTANT_Integer:
case CONSTANT_Float:
- jcf->cpool.data[i] = JCF_readu4 (jcf);
+ jcf->cpool.data[i].w = JCF_readu4 (jcf);
break;
case CONSTANT_Long:
case CONSTANT_Double:
- jcf->cpool.data[i] = JCF_readu4 (jcf);
+ jcf->cpool.data[i].w = JCF_readu4 (jcf);
i++; /* These take up two spots in the constant pool */
jcf->cpool.tags[i] = 0;
- jcf->cpool.data[i] = JCF_readu4 (jcf);
+ jcf->cpool.data[i].w = JCF_readu4 (jcf);
break;
case CONSTANT_Utf8:
n = JCF_readu2 (jcf);
@@ -311,7 +311,7 @@ jcf_parse_constant_pool (JCF* jcf)
#ifdef HANDLE_CONSTANT_Utf8
HANDLE_CONSTANT_Utf8(jcf, i, n);
#else
- jcf->cpool.data[i] = JCF_TELL(jcf) - 2;
+ jcf->cpool.data[i].w = JCF_TELL(jcf) - 2;
JCF_SKIP (jcf, n);
#endif
break;
diff --git a/gcc/java/jcf.h b/gcc/java/jcf.h
index 0555f362372..c8e6aa7a602 100644
--- a/gcc/java/jcf.h
+++ b/gcc/java/jcf.h
@@ -55,9 +55,17 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */
#endif
struct JCF;
-typedef int (*jcf_filbuf_t) (struct JCF*, int needed);
+typedef int (*jcf_filbuf_t) PARAMS ((struct JCF*, int needed));
-typedef struct CPool {
+union cpool_entry GTY(()) {
+ jword GTY ((tag ("0"))) w;
+ tree GTY ((tag ("1"))) t;
+};
+
+#define cpool_entry_is_tree(tag) \
+ (tag & CONSTANT_ResolvedFlag) || tag == CONSTANT_Utf8
+
+typedef struct CPool GTY(()) {
/* Available number of elements in the constants array, before it
must be re-allocated. */
int capacity;
@@ -65,29 +73,33 @@ typedef struct CPool {
/* The constant_pool_count. */
int count;
- uint8* tags;
+ uint8* GTY((length ("%h.count"))) tags;
- jword* data;
+ union cpool_entry * GTY((length ("%h.count"),
+ desc ("cpool_entry_is_tree (%1.tags%a)"))) data;
} CPool;
struct ZipDirectory;
/* JCF encapsulates the state of reading a Java Class File. */
-typedef struct JCF {
- unsigned char *buffer;
- unsigned char *buffer_end;
- unsigned char *read_ptr;
- unsigned char *read_end;
+typedef struct JCF GTY(()) {
+ unsigned char * GTY ((skip (""))) buffer;
+ unsigned char * GTY ((skip (""))) buffer_end;
+ unsigned char * GTY ((skip (""))) read_ptr;
+ unsigned char * GTY ((skip (""))) read_end;
int java_source : 1;
int right_zip : 1;
int finished : 1;
jcf_filbuf_t filbuf;
- void *read_state;
+ PTR GTY ((skip (""))) read_state;
const char *filename;
const char *classname;
- struct ZipDirectory *zipd; /* Directory entry where it was found */
- JCF_u2 access_flags, this_class, super_class;
+ /* Directory entry where it was found. */
+ struct ZipDirectory * GTY ((skip (""))) zipd;
+ JCF_u2 access_flags;
+ JCF_u2 this_class;
+ JCF_u2 super_class;
CPool cpool;
} JCF;
/*typedef JCF* JCF_FILE;*/
@@ -102,13 +114,13 @@ typedef struct JCF {
#define JPOOL_SIZE(JCF) CPOOL_COUNT(&(JCF)->cpool)
#define JPOOL_TAG(JCF, INDEX) ((JCF)->cpool.tags[INDEX])
/* The INDEX'th constant pool entry as a JCF_u4. */
-#define CPOOL_UINT(CPOOL, INDEX) ((CPOOL)->data[INDEX])
+#define CPOOL_UINT(CPOOL, INDEX) ((CPOOL)->data[INDEX].w)
#define JPOOL_UINT(JCF, INDEX) CPOOL_UINT(&(JCF)->cpool, INDEX) /*deprecated*/
/* The first uint16 of the INDEX'th constant pool entry. */
-#define CPOOL_USHORT1(CPOOL, INDEX) ((CPOOL)->data[INDEX] & 0xFFFF)
+#define CPOOL_USHORT1(CPOOL, INDEX) ((CPOOL)->data[INDEX].w & 0xFFFF)
#define JPOOL_USHORT1(JCF, INDEX) CPOOL_USHORT1(&(JCF)->cpool, INDEX)
/* The second uint16 of the INDEX'th constant pool entry. */
-#define CPOOL_USHORT2(CPOOL, INDEX) ((CPOOL)->data[INDEX] >> 16)
+#define CPOOL_USHORT2(CPOOL, INDEX) ((CPOOL)->data[INDEX].w >> 16)
#define JPOOL_USHORT2(JCF, INDEX) CPOOL_USHORT2(&(JCF)->cpool, INDEX)
#define JPOOL_LONG(JCF, INDEX) \
WORDS_TO_LONG (JPOOL_UINT(JCF, INDEX), JPOOL_UINT(JCF, (INDEX)+1))
@@ -128,9 +140,10 @@ typedef struct JCF {
#define CPOOL_INDEX_IN_RANGE(CPOOL, INDEX) \
((INDEX) > 0 && (INDEX) < CPOOL_COUNT(CPOOL))
-#define CPOOL_FINISH(CPOOL) { \
- if ((CPOOL)->tags) FREE ((CPOOL)->tags); \
- if ((CPOOL)->data) FREE ((CPOOL)->data); }
+#define CPOOL_FINISH(CPOOL) { \
+ (CPOOL)->tags = 0; \
+ (CPOOL)->data = 0; \
+ }
#define JCF_FINISH(JCF) { \
CPOOL_FINISH(&(JCF)->cpool); \
diff --git a/gcc/java/lex.c b/gcc/java/lex.c
index c6744f401e7..976d0cf08af 100644
--- a/gcc/java/lex.c
+++ b/gcc/java/lex.c
@@ -125,7 +125,7 @@ java_init_lex (finput, encoding)
CPC_INSTANCE_INITIALIZER_LIST (ctxp) = NULL_TREE;
memset (ctxp->modifier_ctx, 0, sizeof (ctxp->modifier_ctx));
- memset (current_jcf, 0, sizeof (JCF));
+ current_jcf = ggc_alloc_cleared (sizeof (JCF));
ctxp->current_parsed_class = NULL;
ctxp->package = NULL_TREE;
#endif
diff --git a/gcc/java/lex.h b/gcc/java/lex.h
index 9579036c602..aa9a2beea34 100644
--- a/gcc/java/lex.h
+++ b/gcc/java/lex.h
@@ -96,13 +96,13 @@ struct java_error {
int error;
};
-typedef struct _java_lc {
+typedef struct java_lc_s GTY(()) {
int line;
int prev_col;
int col;
} java_lc;
-typedef struct java_lexer
+struct java_lexer
{
/* The file from which we're reading. */
FILE *finput;
@@ -155,7 +155,8 @@ typedef struct java_lexer
int out_last;
#endif /* HAVE_ICONV */
-} java_lexer;
+};
+typedef struct java_lexer java_lexer;
/* Destroy a lexer object. */
extern void java_destroy_lexer (java_lexer *);
diff --git a/gcc/java/parse.h b/gcc/java/parse.h
index 37731fbd255..a6681afd6f0 100644
--- a/gcc/java/parse.h
+++ b/gcc/java/parse.h
@@ -427,9 +427,6 @@ enum {
INVOKE_VIRTUAL
};
-/* We need the resolution stuff only if we compile jc1 */
-#ifndef JC1_LITE
-
/* Unresolved type identifiers handling. When we process the source
code, we blindly accept an unknown type identifier and try to
resolve it later. When an unknown type identifier is encountered
@@ -509,13 +506,12 @@ typedef struct _jdep {
#define JDEP_RESOLVED_P(J) \
(!(J)->solv || TREE_CODE ((J)->solv) != POINTER_TYPE)
-typedef struct _jdeplist {
+struct jdeplist_s {
jdep *first;
jdep *last;
- struct _jdeplist *next;
-} jdeplist;
-
-#endif /* JC1_LITE */
+ struct jdeplist_s *next;
+};
+typedef struct jdeplist_s jdeplist;
#define CLASSD_FIRST(CD) ((CD)->first)
#define CLASSD_LAST(CD) ((CD)->last)
@@ -727,14 +723,15 @@ typedef struct _jdeplist {
#define DECL_INHERITED_SOURCE_LINE(DECL) (DECL_CHECK (DECL)->decl.u2.i)
/* Parser context data structure. */
-struct parser_ctxt {
+struct parser_ctxt GTY(()) {
const char *filename; /* Current filename */
struct parser_ctxt *next;
- java_lexer *lexer; /* Current lexer state */
+ java_lexer * GTY((skip (""))) lexer; /* Current lexer state */
char marker_begining; /* Marker. Should be a sub-struct */
- struct java_line *p_line, *c_line; /* Previous and current line */
+ struct java_line * GTY ((skip (""))) p_line; /* Previous line */
+ struct java_line * GTY ((skip (""))) c_line; /* Current line */
java_lc elc; /* Error's line column info */
int ccb_indent; /* Keep track of {} indent, lexer */
int first_ccb_indent1; /* First { at ident level 1 */
@@ -742,7 +739,7 @@ struct parser_ctxt {
int parser_ccb_indent; /* Keep track of {} indent, parser */
int osb_depth; /* Current depth of [ in an expression */
int osb_limit; /* Limit of this depth */
- int *osb_number; /* Keep track of ['s */
+ int * GTY ((skip (""))) osb_number; /* Keep track of ['s */
int lineno; /* Current lineno */
char marker_end; /* End marker. Should be a sub-struct */
@@ -761,13 +758,12 @@ struct parser_ctxt {
/* Flag to report certain errors (fix this documentation. FIXME) */
unsigned class_err:1;
- /* This section is defined only if we compile jc1 */
-#ifndef JC1_LITE
+ /* This section is used only if we compile jc1 */
tree modifier_ctx [12]; /* WFL of modifiers */
tree class_type; /* Current class */
tree function_decl; /* Current function decl, save/restore */
- struct JCF *current_jcf; /* CU jcf */
+ struct JCF * current_jcf; /* CU jcf */
int prevent_ese; /* Prevent expression statement error */
@@ -778,7 +774,7 @@ struct parser_ctxt {
/* These two lists won't survive file traversal */
tree class_list; /* List of classes in a CU */
- jdeplist *classd_list; /* Classe dependencies in a CU */
+ jdeplist * GTY((skip (""))) classd_list; /* Classe dependencies in a CU */
tree current_parsed_class; /* Class currently parsed */
tree current_parsed_class_un; /* Curr. parsed class unqualified name */
@@ -801,7 +797,6 @@ struct parser_ctxt {
constructor. This flag is used to trap
illegal argument usage during an
explicit constructor invocation. */
-#endif /* JC1_LITE */
};
/* A set of macros to push/pop/access the currently parsed class. */
@@ -947,7 +942,7 @@ ATTRIBUTE_NORETURN
;
extern void java_expand_classes (void);
-extern struct parser_ctxt *ctxp;
-extern struct parser_ctxt *ctxp_for_generation;
+extern GTY(()) struct parser_ctxt *ctxp;
+extern GTY(()) struct parser_ctxt *ctxp_for_generation;
#endif /* ! GCC_JAVA_PARSE_H */
diff --git a/gcc/java/parse.y b/gcc/java/parse.y
index 3dbe3b3ed3a..c67a42e11f6 100644
--- a/gcc/java/parse.y
+++ b/gcc/java/parse.y
@@ -304,13 +304,16 @@ static tree maybe_build_thisn_access_method (tree);
static tree build_outer_field_access (tree, tree);
static tree build_outer_field_access_methods (tree);
-static tree build_outer_field_access_expr (int, tree, tree, tree, tree);
+static tree build_outer_field_access_expr (int, tree, tree,
+ tree, tree);
static tree build_outer_method_access_method (tree);
static tree build_new_access_id (void);
-static tree build_outer_field_access_method (tree, tree, tree, tree, tree);
+static tree build_outer_field_access_method (tree, tree, tree,
+ tree, tree);
static int outer_field_access_p (tree, tree);
-static int outer_field_expanded_access_p (tree, tree *, tree *, tree *);
+static int outer_field_expanded_access_p (tree, tree *,
+ tree *, tree *);
static tree outer_field_access_fix (tree, tree, tree);
static tree build_incomplete_class_ref (int, tree);
static tree patch_incomplete_class_ref (tree);
@@ -321,7 +324,6 @@ static void add_inner_class_fields (tree, tree);
static tree build_dot_class_method (tree);
static tree build_dot_class_method_invocation (tree);
static void create_new_parser_context (int);
-static void mark_parser_ctxt (void *);
static tree maybe_build_class_init_for_field (tree, tree);
static int attach_init_test_initialization_flags (PTR *, PTR);
@@ -594,18 +596,7 @@ static GTY(()) tree src_parse_roots[1];
%%
/* 19.2 Production from 2.3: The Syntactic Grammar */
-goal:
- {
- /* Register static variables with the garbage
- collector. */
- ggc_add_root (&ctxp, 1,
- sizeof (struct parser_ctxt *),
- mark_parser_ctxt);
- ggc_add_root (&ctxp_for_generation, 1,
- sizeof (struct parser_ctxt *),
- mark_parser_ctxt);
- }
- compilation_unit
+goal: compilation_unit
{}
;
@@ -2669,7 +2660,7 @@ create_new_parser_context (copy_from_previous)
{
struct parser_ctxt *new;
- new = (struct parser_ctxt *)xmalloc(sizeof (struct parser_ctxt));
+ new = (struct parser_ctxt *) ggc_alloc (sizeof (struct parser_ctxt));
if (copy_from_previous)
{
memcpy ((PTR)new, (PTR)ctxp, sizeof (struct parser_ctxt));
@@ -2730,8 +2721,6 @@ java_pop_parser_context (generate)
toFree->next = ctxp_for_generation;
ctxp_for_generation = toFree;
}
- else
- free (toFree);
}
/* Create a parser context for the use of saving some global
@@ -2830,10 +2819,6 @@ java_parser_context_resume ()
/* Re-installed the data for the parsing to carry on */
memcpy (&ctxp->marker_begining, &old->marker_begining,
(size_t)(&ctxp->marker_end - &ctxp->marker_begining));
-
- /* Buffer context can now be discarded */
- free (saver);
- free (old);
}
/* Add a new anchor node to which all statement(s) initializing static
@@ -6732,10 +6717,9 @@ process_imports ()
tree to_be_found = EXPR_WFL_NODE (TREE_PURPOSE (import));
char *original_name;
- obstack_grow0 (&temporary_obstack,
- IDENTIFIER_POINTER (to_be_found),
- IDENTIFIER_LENGTH (to_be_found));
- original_name = obstack_finish (&temporary_obstack);
+ original_name = xmemdup (IDENTIFIER_POINTER (to_be_found),
+ IDENTIFIER_LENGTH (to_be_found),
+ IDENTIFIER_LENGTH (to_be_found) + 1);
/* Don't load twice something already defined. */
if (IDENTIFIER_CLASS_VALUE (to_be_found))
@@ -6771,7 +6755,7 @@ process_imports ()
error_found = 1;
}
- obstack_free (&temporary_obstack, original_name);
+ free (original_name);
if (error_found)
return 1;
}
@@ -16190,42 +16174,6 @@ resolve_qualified_name (name, context)
}
#endif
-/* Mark P, which is really a `struct parser_ctxt **' for GC. */
-
-static void
-mark_parser_ctxt (p)
- void *p;
-{
- struct parser_ctxt *pc = *((struct parser_ctxt **) p);
-#ifndef JC1_LITE
- size_t i;
-#endif
-
- if (!pc)
- return;
-
-#ifndef JC1_LITE
- for (i = 0; i < ARRAY_SIZE (pc->modifier_ctx); ++i)
- ggc_mark_tree (pc->modifier_ctx[i]);
- ggc_mark_tree (pc->class_type);
- ggc_mark_tree (pc->function_decl);
- ggc_mark_tree (pc->package);
- ggc_mark_tree (pc->class_list);
- ggc_mark_tree (pc->current_parsed_class);
- ggc_mark_tree (pc->current_parsed_class_un);
- ggc_mark_tree (pc->non_static_initialized);
- ggc_mark_tree (pc->static_initialized);
- ggc_mark_tree (pc->instance_initializers);
- ggc_mark_tree (pc->import_list);
- ggc_mark_tree (pc->import_demand_list);
- ggc_mark_tree (pc->current_loop);
- ggc_mark_tree (pc->current_labeled_block);
-#endif /* JC1_LITE */
-
- if (pc->next)
- mark_parser_ctxt (&pc->next);
-}
-
void
init_src_parse ()
{
diff --git a/gcc/mkdeps.c b/gcc/mkdeps.c
index 26504e14afa..0c573cd4d82 100644
--- a/gcc/mkdeps.c
+++ b/gcc/mkdeps.c
@@ -291,3 +291,77 @@ deps_phony_targets (d, fp)
putc ('\n', fp);
}
}
+
+/* Write out a deps buffer to a file, in a form that can be read back
+ with deps_restore. Returns nonzero on error, in which case the
+ error number will be in errno. */
+
+int
+deps_save (deps, f)
+ struct deps *deps;
+ FILE *f;
+{
+ unsigned int i;
+
+ /* The cppreader structure contains makefile dependences. Write out this
+ structure. */
+
+ /* The number of dependences. */
+ if (fwrite (&deps->ndeps, sizeof (deps->ndeps), 1, f) != 1)
+ return -1;
+ /* The length of each dependence followed by the string. */
+ for (i = 0; i < deps->ndeps; i++)
+ {
+ size_t num_to_write = strlen (deps->depv[i]);
+ if (fwrite (&num_to_write, sizeof (size_t), 1, f) != 1)
+ return -1;
+ if (fwrite (deps->depv[i], num_to_write, 1, f) != 1)
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Read back dependency information written with deps_save into
+ the deps buffer. The third argument may be NULL, in which case
+ the dependency information is just skipped, or it may be a filename,
+ in which case that filename is skipped. */
+
+int
+deps_restore (deps, fd, self)
+ struct deps *deps;
+ FILE *fd;
+ const char *self;
+{
+ unsigned int i, count;
+ size_t num_to_read;
+ size_t buf_size = 512;
+ char *buf = (char *) xmalloc (buf_size);
+
+ /* Number of dependences. */
+ if (fread (&count, 1, sizeof (count), fd) != sizeof (count))
+ return -1;
+
+ /* The length of each dependence string, followed by the string. */
+ for (i = 0; i < count; i++)
+ {
+ /* Read in # bytes in string. */
+ if (fread (&num_to_read, 1, sizeof (size_t), fd) != sizeof (size_t))
+ return -1;
+ if (buf_size < num_to_read + 1)
+ {
+ buf_size = num_to_read + 1 + 127;
+ buf = xrealloc (buf, buf_size);
+ }
+ if (fread (buf, 1, num_to_read, fd) != num_to_read)
+ return -1;
+ buf[num_to_read] = '\0';
+
+ /* Generate makefile dependencies from .pch if -nopch-deps. */
+ if (self != NULL && strcmp (buf, self) != 0)
+ deps_add_dep (deps, buf);
+ }
+
+ free (buf);
+ return 0;
+}
diff --git a/gcc/mkdeps.h b/gcc/mkdeps.h
index fa79b86591b..2be8f81a99c 100644
--- a/gcc/mkdeps.h
+++ b/gcc/mkdeps.h
@@ -53,6 +53,17 @@ extern void deps_add_dep PARAMS ((struct deps *, const char *));
extern void deps_write PARAMS ((const struct deps *, FILE *,
unsigned int));
+/* Write out a deps buffer to a file, in a form that can be read back
+ with deps_restore. Returns nonzero on error, in which case the
+ error number will be in errno. */
+extern int deps_save PARAMS ((struct deps *, FILE *));
+
+/* Read back dependency information written with deps_save into
+ the deps buffer. The third argument may be NULL, in which case
+ the dependency information is just skipped, or it may be a filename,
+ in which case that filename is skipped. */
+extern int deps_restore PARAMS ((struct deps *, FILE *, const char *));
+
/* For each dependency *except the first*, emit a dummy rule for that
file, causing it to depend on nothing. This is used to work around
the intermediate-file deletion misfeature in Make, in some
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 3f0d3391d5e..3a5de01b2db 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -56,6 +56,7 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
#include "toplev.h"
#include "ggc.h"
+#include "varray.h"
#include "debug.h"
#include "target.h"
#include "diagnostic.h"
diff --git a/gcc/optabs.h b/gcc/optabs.h
index e3890fe9a90..2ff8fec62dd 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -1,5 +1,5 @@
/* Definitions for code generation pass of GNU compiler.
- Copyright (C) 2001 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
@@ -246,7 +246,7 @@ extern enum insn_code reload_in_optab[NUM_MACHINE_MODES];
extern enum insn_code reload_out_optab[NUM_MACHINE_MODES];
/* Contains the optab used for each rtx code. */
-extern optab code_to_optab[NUM_RTX_CODE + 1];
+extern GTY(()) optab code_to_optab[NUM_RTX_CODE + 1];
typedef rtx (*rtxfun) PARAMS ((rtx));
diff --git a/gcc/stringpool.c b/gcc/stringpool.c
index f3b34b139cf..1edb46f66a6 100644
--- a/gcc/stringpool.c
+++ b/gcc/stringpool.c
@@ -1,5 +1,5 @@
/* String pool for GCC.
- Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
@@ -50,7 +50,6 @@ static struct obstack string_stack;
static hashnode alloc_node PARAMS ((hash_table *));
static int mark_ident PARAMS ((struct cpp_reader *, hashnode, const PTR));
-static void mark_ident_hash PARAMS ((void *));
/* Initialize the string pool. */
void
@@ -60,7 +59,6 @@ init_stringpool ()
ident_hash = ht_create (14);
ident_hash->alloc_node = alloc_node;
gcc_obstack_init (&string_stack);
- ggc_add_root (&ident_hash, 1, sizeof ident_hash, mark_ident_hash);
}
/* Allocate a hash node. */
@@ -160,15 +158,94 @@ mark_ident (pfile, h, v)
hashnode h;
const PTR v ATTRIBUTE_UNUSED;
{
- ggc_mark_tree (HT_IDENT_TO_GCC_IDENT (h));
+ gt_ggc_m_9tree_node (HT_IDENT_TO_GCC_IDENT (h));
return 1;
}
-/* Mark all identifiers for GC. */
+/* Mark the trees hanging off the identifier node for GGC. These are
+ handled specially (not using gengtype) because of the special
+ treatment for strings. */
-static void
-mark_ident_hash (arg)
- PTR arg ATTRIBUTE_UNUSED;
+void
+ggc_mark_stringpool ()
{
ht_forall (ident_hash, mark_ident, NULL);
}
+
+/* Strings are _not_ GCed, but this routine exists so that a separate
+ roots table isn't needed for the few global variables that refer
+ to strings. */
+
+void
+gt_ggc_m_S (x)
+ void *x ATTRIBUTE_UNUSED;
+{
+}
+
+/* Pointer-walking routine for strings (not very interesting, since
+ strings don't contain pointers). */
+
+void
+gt_pch_p_S (obj, x, op, cookie)
+ void *obj ATTRIBUTE_UNUSED;
+ void *x ATTRIBUTE_UNUSED;
+ gt_pointer_operator op ATTRIBUTE_UNUSED;
+ void *cookie ATTRIBUTE_UNUSED;
+{
+}
+
+/* PCH pointer-walking routine for strings. */
+
+void
+gt_pch_n_S (x)
+ const void *x;
+{
+ gt_pch_note_object ((void *)x, (void *)x, &gt_pch_p_S);
+}
+
+/* Handle saving and restoring the string pool for PCH. */
+
+struct string_pool_data GTY(())
+{
+ tree * GTY((length ("%h.nslots"))) entries;
+ unsigned int nslots;
+ unsigned int nelements;
+};
+
+static GTY(()) struct string_pool_data * spd;
+
+void
+gt_pch_save_stringpool ()
+{
+ unsigned int i;
+
+ spd = ggc_alloc (sizeof (*spd));
+ spd->nslots = ident_hash->nslots;
+ spd->nelements = ident_hash->nelements;
+ spd->entries = ggc_alloc (sizeof (tree *) * spd->nslots);
+ for (i = 0; i < spd->nslots; i++)
+ if (ident_hash->entries[i] != NULL)
+ spd->entries[i] = HT_IDENT_TO_GCC_IDENT (ident_hash->entries[i]);
+ else
+ spd->entries[i] = NULL;
+}
+
+void
+gt_pch_restore_stringpool ()
+{
+ unsigned int i;
+
+ ident_hash->nslots = spd->nslots;
+ ident_hash->nelements = spd->nelements;
+ ident_hash->entries = xrealloc (ident_hash->entries,
+ sizeof (hashnode) * spd->nslots);
+ for (i = 0; i < spd->nslots; i++)
+ if (spd->entries[i] != NULL)
+ ident_hash->entries[i] = GCC_IDENT_TO_HT_IDENT (spd->entries[i]);
+ else
+ ident_hash->entries[i] = NULL;
+
+ spd = NULL;
+}
+
+#include "gt-stringpool.h"
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 8168b989ade..e1c6e0287ae 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,87 @@
+2003-01-09 Geoffrey Keating <geoffk@apple.com>
+
+ Merge from pch-branch:
+
+ 2002-12-23 Geoffrey Keating <geoffk@apple.com>
+
+ * gcc.dg/pch/cpp-1.h: New.
+ * gcc.dg/pch/cpp-1.c: New.
+ * gcc.dg/pch/cpp-2.h: New.
+ * gcc.dg/pch/cpp-2.c: New.
+
+ 2002-11-19 Geoffrey Keating <geoffk@apple.com>
+
+ * gcc.dg/pch/except-1.h: New.
+ * gcc.dg/pch/except-1.c: New.
+
+ 2002-11-13 Geoffrey Keating <geoffk@apple.com>
+
+ * gcc.dg/pch/pch.exp: Ensure that <test>.hp doesn't exist before
+ running test.
+ * gcc.dg/pch: Include *.hp not *.h.
+ * gcc.dg/pch/system-1.h: New.
+ * gcc.dg/pch/system-1.c: New.
+
+ 2002-11-11 Geoffrey Keating <geoffk@apple.com>
+
+ * gcc.dg/pch/pch.exp: Compare .s files with/without PCH,
+ rather than trying to build and run a program using PCH.
+ * gcc.dg/pch: Remove dg-do commands from test files.
+
+ 2002-11-08 Geoffrey Keating <geoffk@apple.com>
+
+ * gcc.dg/pch/macro-3.c: New.
+ * gcc.dg/pch/macro-3.h: New.
+
+ 2002-11-04 Geoffrey Keating <geoffk@apple.com>
+
+ * gcc.dg/pch/common-1.c: New.
+ * gcc.dg/pch/common-1.h: New.
+ * gcc.dg/pch/decl-1.c: New.
+ * gcc.dg/pch/decl-1.h: New.
+ * gcc.dg/pch/decl-2.c: New.
+ * gcc.dg/pch/decl-2.h: New.
+ * gcc.dg/pch/decl-3.c: New.
+ * gcc.dg/pch/decl-3.h: New.
+ * gcc.dg/pch/decl-4.c: New.
+ * gcc.dg/pch/decl-4.h: New.
+ * gcc.dg/pch/decl-5.c: New.
+ * gcc.dg/pch/decl-5.h: New.
+ * gcc.dg/pch/global-1.c: New.
+ * gcc.dg/pch/global-1.h: New.
+ * gcc.dg/pch/inline-1.c: New.
+ * gcc.dg/pch/inline-1.h: New.
+ * gcc.dg/pch/inline-2.c: New.
+ * gcc.dg/pch/inline-2.h: New.
+ * gcc.dg/pch/static-1.c: New.
+ * gcc.dg/pch/static-1.h: New.
+ * gcc.dg/pch/static-2.c: New.
+ * gcc.dg/pch/static-2.h: New.
+
+ 2002-09-01 Geoffrey Keating <geoffk@redhat.com>
+
+ * g++.dg/pch/pch.exp: Better handle failing testcases.
+ * gcc.dg/pch/pch.exp: Likewise.
+ * gcc.dg/pch/macro-1.c: New.
+ * gcc.dg/pch/macro-1.h: New.
+ * gcc.dg/pch/macro-2.c: New.
+ * gcc.dg/pch/macro-2.h: New.
+
+ 2002-08-27 Geoffrey Keating <geoffk@redhat.com>
+
+ * g++.dg/dg.exp: Treat files in pch/ specially.
+ * g++.dg/pch/pch.exp: New file.
+ * g++.dg/pch/empty.H: New file.
+ * g++.dg/pch/empty.C: New file.
+ * lib/g++-dg.exp (g++-dg-test): Add case for when $do_what is
+ "precompile".
+
+ * gcc.dg/pch/pch.exp: New file.
+ * gcc.dg/pch/empty.h: New file.
+ * gcc.dg/pch/empty.c: New file.
+ * lib/gcc-dg.exp (gcc-dg-test): Add case for when $do_what is
+ "precompile".
+
2003-01-09 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
* g++.dg/template/friend14.C: New test.
diff --git a/gcc/testsuite/g++.dg/dg.exp b/gcc/testsuite/g++.dg/dg.exp
index ea96197332f..d9839608733 100644
--- a/gcc/testsuite/g++.dg/dg.exp
+++ b/gcc/testsuite/g++.dg/dg.exp
@@ -35,6 +35,7 @@ set tests [prune $tests $srcdir/$subdir/bprob/*]
set tests [prune $tests $srcdir/$subdir/compat/*]
set tests [prune $tests $srcdir/$subdir/debug/*]
set tests [prune $tests $srcdir/$subdir/gcov/*]
+set tests [prune $tests $srcdir/$subdir/pch/*]
set tests [prune $tests $srcdir/$subdir/special/*]
set tests [prune $tests $srcdir/$subdir/tls/*]
diff --git a/gcc/testsuite/g++.dg/pch/empty.C b/gcc/testsuite/g++.dg/pch/empty.C
new file mode 100644
index 00000000000..7aef099f3ef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pch/empty.C
@@ -0,0 +1,5 @@
+#include "empty.Hp"
+int main()
+{
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/pch/empty.H b/gcc/testsuite/g++.dg/pch/empty.H
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pch/empty.H
diff --git a/gcc/testsuite/g++.dg/pch/pch.exp b/gcc/testsuite/g++.dg/pch/pch.exp
new file mode 100644
index 00000000000..8507e355f53
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pch/pch.exp
@@ -0,0 +1,100 @@
+# Copyright (C) 1997, 2002 Free Software Foundation, Inc.
+
+# This program 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 of the License, or
+# (at your option) any later version.
+#
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# GCC testsuite for precompiled header interaction,
+# that uses the `dg.exp' driver.
+
+# Load support procs.
+load_lib "g++-dg.exp"
+
+# Initialize `dg'.
+dg-init
+
+set old_dg_do_what_default "${dg-do-what-default}"
+
+# Main loop.
+foreach test [lsort [glob -nocomplain $srcdir/$subdir/*.C]] {
+ global runtests dg-do-what-default
+
+ # If we're only testing specific files and this isn't one of them, skip it.
+ if ![runtest_file_p $runtests $test] {
+ continue
+ }
+ set nshort [file tail [file dirname $test]]/[file tail $test]
+ set bname "[file rootname [file tail $test]]"
+
+ catch { file delete "$bname.Hp.pch" }
+ catch { file delete "$bname.H.pch" }
+ catch { file delete "$bname.s" }
+ catch { file delete "$bname.s-pch" }
+ catch { file delete "$bname.Hp" }
+
+ # We don't try to use the loop-optimizing options, since they are highly
+ # unlikely to make any difference to PCH.
+ foreach flags { "-g" "-O2 -g" "-O2" } {
+ verbose "Testing $nshort, $flags" 1
+
+ # For the header files, the default is to precompile.
+ set dg-do-what-default precompile
+ dg-test -keep-output "[file rootname $test].H" $flags ""
+
+ # For the rest, the default is to compile to .s.
+ set dg-do-what-default compile
+
+ if { [ file exists "$bname.H.pch" ] } {
+ # To ensure that the PCH is used, not the original header,
+ # the actual PCH file is renamed to "<foo>.Hp.pch".
+ file rename "$bname.H.pch" "$bname.Hp.pch"
+ if { [ is_remote host ] } {
+ remote_download host "$bname.Hp.pch"
+ }
+
+ dg-test -keep-output $test $flags "-I."
+ file delete "$bname.Hp.pch"
+ if { [ file exists "$bname.s" ] } {
+ file rename "$bname.s" "$bname.s-pch"
+ if { [ is_remote host ] } {
+ remote_upload host "[file rootname $test].H" "$bname.Hp"
+ } else {
+ file copy "[file rootname $test].H" "$bname.Hp"
+ }
+ dg-test -keep-output $test $flags "-I."
+ remote_file host delete "$bname.Hp"
+ set tmp [ diff "$bname.s" "$bname.s-pch" ]
+ if { $tmp == 0 } {
+ untested "$nshort $flags assembly comparison"
+ } elseif { $tmp == 1 } {
+ pass "$nshort $flags assembly comparison"
+ } else {
+ fail "$nshort $flags assembly comparison"
+ }
+ file delete "$bname.s"
+ file delete "$bname.s-pch"
+ } else {
+ untested "$nshort $flags assembly comparison"
+ }
+
+ } else {
+ untested $nshort
+ untested "$nshort $flags assembly comparison"
+ }
+ }
+}
+
+set dg-do-what-default "$old_dg_do_what_default"
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/g++.dg/pch/system-1.C b/gcc/testsuite/g++.dg/pch/system-1.C
new file mode 100644
index 00000000000..a0444bc5941
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pch/system-1.C
@@ -0,0 +1,7 @@
+#include "system-1.Hp"
+
+int main()
+{
+ std::cout << "hello world!" << '\n';
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/pch/system-1.H b/gcc/testsuite/g++.dg/pch/system-1.H
new file mode 100644
index 00000000000..604782e4dc7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pch/system-1.H
@@ -0,0 +1 @@
+#include <iostream>
diff --git a/gcc/testsuite/gcc.dg/pch/common-1.c b/gcc/testsuite/gcc.dg/pch/common-1.c
new file mode 100644
index 00000000000..dcf148a2a72
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/common-1.c
@@ -0,0 +1,3 @@
+#include "common-1.hp"
+int foo2 = 3;
+int zz = 2;
diff --git a/gcc/testsuite/gcc.dg/pch/common-1.h b/gcc/testsuite/gcc.dg/pch/common-1.h
new file mode 100644
index 00000000000..971e1996a24
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/common-1.h
@@ -0,0 +1,3 @@
+static int foo1 = 9;
+int foo2;
+extern int zz;
diff --git a/gcc/testsuite/gcc.dg/pch/cpp-1.c b/gcc/testsuite/gcc.dg/pch/cpp-1.c
new file mode 100644
index 00000000000..43256cad545
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/cpp-1.c
@@ -0,0 +1,4 @@
+#include "cpp-1.hp"
+#if !defined(__GNUC__)
+panic! panic!
+#endif
diff --git a/gcc/testsuite/gcc.dg/pch/cpp-1.h b/gcc/testsuite/gcc.dg/pch/cpp-1.h
new file mode 100644
index 00000000000..6e25b021ab5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/cpp-1.h
@@ -0,0 +1 @@
+/* Empty. */
diff --git a/gcc/testsuite/gcc.dg/pch/cpp-2.c b/gcc/testsuite/gcc.dg/pch/cpp-2.c
new file mode 100644
index 00000000000..b76c22cdb04
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/cpp-2.c
@@ -0,0 +1,4 @@
+/* { dg-options "-Wunknown-pragmas -I." } */
+#include "cpp-2.hp"
+#pragma GCC poison not_used
+
diff --git a/gcc/testsuite/gcc.dg/pch/cpp-2.h b/gcc/testsuite/gcc.dg/pch/cpp-2.h
new file mode 100644
index 00000000000..6e25b021ab5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/cpp-2.h
@@ -0,0 +1 @@
+/* Empty. */
diff --git a/gcc/testsuite/gcc.dg/pch/decl-1.c b/gcc/testsuite/gcc.dg/pch/decl-1.c
new file mode 100644
index 00000000000..e4120704d9b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/decl-1.c
@@ -0,0 +1,2 @@
+#include "decl-1.hp"
+int main(void) { return foo; }
diff --git a/gcc/testsuite/gcc.dg/pch/decl-1.h b/gcc/testsuite/gcc.dg/pch/decl-1.h
new file mode 100644
index 00000000000..399f5d3e7f4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/decl-1.h
@@ -0,0 +1 @@
+extern int foo;
diff --git a/gcc/testsuite/gcc.dg/pch/decl-2.c b/gcc/testsuite/gcc.dg/pch/decl-2.c
new file mode 100644
index 00000000000..c374a17e3f7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/decl-2.c
@@ -0,0 +1,2 @@
+#include "decl-2.hp"
+int main(void) { return fun (1, 2); }
diff --git a/gcc/testsuite/gcc.dg/pch/decl-2.h b/gcc/testsuite/gcc.dg/pch/decl-2.h
new file mode 100644
index 00000000000..99c37269097
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/decl-2.h
@@ -0,0 +1,3 @@
+extern int fun (int a, int b);
+
+
diff --git a/gcc/testsuite/gcc.dg/pch/decl-3.c b/gcc/testsuite/gcc.dg/pch/decl-3.c
new file mode 100644
index 00000000000..9c95b9ad08e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/decl-3.c
@@ -0,0 +1,11 @@
+#include "decl-3.hp"
+
+foo_p bar (void)
+{
+ return foop;
+}
+
+struct foo *bar2 (void)
+{
+ return foop;
+}
diff --git a/gcc/testsuite/gcc.dg/pch/decl-3.h b/gcc/testsuite/gcc.dg/pch/decl-3.h
new file mode 100644
index 00000000000..787d480f208
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/decl-3.h
@@ -0,0 +1,3 @@
+struct foo;
+typedef struct foo *foo_p;
+extern foo_p foop;
diff --git a/gcc/testsuite/gcc.dg/pch/decl-4.c b/gcc/testsuite/gcc.dg/pch/decl-4.c
new file mode 100644
index 00000000000..3efe3829ffc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/decl-4.c
@@ -0,0 +1,9 @@
+#include "decl-4.hp"
+
+int bar (foo_p f)
+{
+ if (f->a + foop->a)
+ return f->c->b + foop->b;
+ else
+ return foop->c->b + f->a;
+}
diff --git a/gcc/testsuite/gcc.dg/pch/decl-4.h b/gcc/testsuite/gcc.dg/pch/decl-4.h
new file mode 100644
index 00000000000..3fb220032e0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/decl-4.h
@@ -0,0 +1,7 @@
+typedef struct foo {
+ int a;
+ char b;
+ struct foo *c;
+} foo_s;
+typedef struct foo *foo_p;
+extern foo_p foop;
diff --git a/gcc/testsuite/gcc.dg/pch/decl-5.c b/gcc/testsuite/gcc.dg/pch/decl-5.c
new file mode 100644
index 00000000000..f94b33a1363
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/decl-5.c
@@ -0,0 +1,2 @@
+#include "decl-5.hp"
+static int (*t)(void) = foo;
diff --git a/gcc/testsuite/gcc.dg/pch/decl-5.h b/gcc/testsuite/gcc.dg/pch/decl-5.h
new file mode 100644
index 00000000000..914983c4963
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/decl-5.h
@@ -0,0 +1 @@
+extern int foo(void);
diff --git a/gcc/testsuite/gcc.dg/pch/empty.c b/gcc/testsuite/gcc.dg/pch/empty.c
new file mode 100644
index 00000000000..330876cc7c7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/empty.c
@@ -0,0 +1,8 @@
+/* Yes, it's called "empty" because it has no contents at all.
+ Even this comment goes here, rather than in empty.h. */
+#include "empty.hp"
+
+int main(void)
+{
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pch/empty.h b/gcc/testsuite/gcc.dg/pch/empty.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/empty.h
diff --git a/gcc/testsuite/gcc.dg/pch/except-1.c b/gcc/testsuite/gcc.dg/pch/except-1.c
new file mode 100644
index 00000000000..0332609de2d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/except-1.c
@@ -0,0 +1,7 @@
+/* { dg-options "-fexceptions -I." } */
+#include "except-1.hp"
+
+int main(void)
+{
+ return foo(1);
+}
diff --git a/gcc/testsuite/gcc.dg/pch/except-1.h b/gcc/testsuite/gcc.dg/pch/except-1.h
new file mode 100644
index 00000000000..33a893d1533
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/except-1.h
@@ -0,0 +1,6 @@
+/* { dg-options "-fexceptions" } */
+extern inline int
+foo(int a)
+{
+ return a + 1;
+}
diff --git a/gcc/testsuite/gcc.dg/pch/global-1.c b/gcc/testsuite/gcc.dg/pch/global-1.c
new file mode 100644
index 00000000000..4cab062345e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/global-1.c
@@ -0,0 +1,2 @@
+#include "global-1.hp"
+const int bar = 3;
diff --git a/gcc/testsuite/gcc.dg/pch/global-1.h b/gcc/testsuite/gcc.dg/pch/global-1.h
new file mode 100644
index 00000000000..26efffcb2bb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/global-1.h
@@ -0,0 +1 @@
+const int foo = 2;
diff --git a/gcc/testsuite/gcc.dg/pch/inline-1.c b/gcc/testsuite/gcc.dg/pch/inline-1.c
new file mode 100644
index 00000000000..7fc32d7f766
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/inline-1.c
@@ -0,0 +1,10 @@
+#include "inline-1.hp"
+int bar(int a, int b)
+{
+ return foo(a) + b;
+}
+
+int baz(void)
+{
+ return foo(3);
+}
diff --git a/gcc/testsuite/gcc.dg/pch/inline-1.h b/gcc/testsuite/gcc.dg/pch/inline-1.h
new file mode 100644
index 00000000000..e8f1d6f138f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/inline-1.h
@@ -0,0 +1,5 @@
+extern inline int
+foo(int a)
+{
+ return a * 2 + 1;
+}
diff --git a/gcc/testsuite/gcc.dg/pch/inline-2.c b/gcc/testsuite/gcc.dg/pch/inline-2.c
new file mode 100644
index 00000000000..7792c828b92
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/inline-2.c
@@ -0,0 +1,12 @@
+#include "inline-2.hp"
+extern inline char
+bar(int a)
+{
+ return foo(a)[0];
+}
+
+extern inline char
+baz(void)
+{
+ return foo(0)[0];
+}
diff --git a/gcc/testsuite/gcc.dg/pch/inline-2.h b/gcc/testsuite/gcc.dg/pch/inline-2.h
new file mode 100644
index 00000000000..7d90c63deb9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/inline-2.h
@@ -0,0 +1,5 @@
+extern inline const char *
+foo(int a)
+{
+ return "abcdefgh"+a;
+}
diff --git a/gcc/testsuite/gcc.dg/pch/macro-1.c b/gcc/testsuite/gcc.dg/pch/macro-1.c
new file mode 100644
index 00000000000..3775004a77b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/macro-1.c
@@ -0,0 +1,6 @@
+#include "macro-1.hp"
+
+int main(void)
+{
+ return DEFINED_VALUE + 1 - DEFINED_PARAM (3);
+}
diff --git a/gcc/testsuite/gcc.dg/pch/macro-1.h b/gcc/testsuite/gcc.dg/pch/macro-1.h
new file mode 100644
index 00000000000..5d5b3f4ca65
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/macro-1.h
@@ -0,0 +1,2 @@
+#define DEFINED_VALUE 3
+#define DEFINED_PARAM(x) (x+1)
diff --git a/gcc/testsuite/gcc.dg/pch/macro-2.c b/gcc/testsuite/gcc.dg/pch/macro-2.c
new file mode 100644
index 00000000000..d058e2bb869
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/macro-2.c
@@ -0,0 +1,8 @@
+#define DEFINED_VALUE_2 3
+
+#include "macro-2.hp"
+
+int main(void)
+{
+ return DEFINED_VALUE - DEFINED_VALUE_2;
+}
diff --git a/gcc/testsuite/gcc.dg/pch/macro-2.h b/gcc/testsuite/gcc.dg/pch/macro-2.h
new file mode 100644
index 00000000000..6152a84a877
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/macro-2.h
@@ -0,0 +1,2 @@
+#define DEFINED_VALUE 3
+
diff --git a/gcc/testsuite/gcc.dg/pch/macro-3.c b/gcc/testsuite/gcc.dg/pch/macro-3.c
new file mode 100644
index 00000000000..40ee46e4f3a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/macro-3.c
@@ -0,0 +1,8 @@
+#define DEFINED_FUNC_2(x) (3 + (x))
+
+#include "macro-3.hp"
+
+int main(void)
+{
+ return DEFINED_FUNC (1) - DEFINED_FUNC_2 (-1);
+}
diff --git a/gcc/testsuite/gcc.dg/pch/macro-3.h b/gcc/testsuite/gcc.dg/pch/macro-3.h
new file mode 100644
index 00000000000..d394792a342
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/macro-3.h
@@ -0,0 +1,2 @@
+#define DEFINED_FUNC(x) 3 - (x)
+
diff --git a/gcc/testsuite/gcc.dg/pch/pch.exp b/gcc/testsuite/gcc.dg/pch/pch.exp
new file mode 100644
index 00000000000..69422ca3ef0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/pch.exp
@@ -0,0 +1,100 @@
+# Copyright (C) 1997, 2002 Free Software Foundation, Inc.
+
+# This program 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 of the License, or
+# (at your option) any later version.
+#
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# GCC testsuite for precompiled header interaction,
+# that uses the `dg.exp' driver.
+
+# Load support procs.
+load_lib gcc-dg.exp
+
+# Initialize `dg'.
+dg-init
+
+set old_dg_do_what_default "${dg-do-what-default}"
+
+# Main loop.
+foreach test [lsort [glob -nocomplain $srcdir/$subdir/*.c]] {
+ global runtests torture_without_loops dg-do-what-default
+
+ # If we're only testing specific files and this isn't one of them, skip it.
+ if ![runtest_file_p $runtests $test] {
+ continue
+ }
+ set nshort [file tail [file dirname $test]]/[file tail $test]
+ set bname "[file rootname [file tail $test]]"
+
+ catch { file delete "$bname.hp.pch" }
+ catch { file delete "$bname.h.pch" }
+ catch { file delete "$bname.s" }
+ catch { file delete "$bname.s-pch" }
+ catch { file delete "$bname.hp" }
+
+ # We don't try to use the loop-optimizing options, since they are highly
+ # unlikely to make any difference to PCH.
+ foreach flags $torture_without_loops {
+ verbose "Testing $nshort, $flags" 1
+
+ # For the header files, the default is to precompile.
+ set dg-do-what-default precompile
+ dg-test -keep-output "[file rootname $test].h" $flags ""
+
+ # For the rest, the default is to compile to .s.
+ set dg-do-what-default compile
+
+ if { [ file exists "$bname.h.pch" ] } {
+ # To ensure that the PCH is used, not the original header,
+ # the actual PCH file is renamed to "<foo>.hp.pch".
+ file rename "$bname.h.pch" "$bname.hp.pch"
+ if { [ is_remote host ] } {
+ remote_download host "$bname.hp.pch"
+ }
+
+ dg-test -keep-output $test $flags "-I."
+ file delete "$bname.hp.pch"
+ if { [ file exists "$bname.s" ] } {
+ file rename "$bname.s" "$bname.s-pch"
+ if { [ is_remote host ] } {
+ remote_upload host "[file rootname $test].h" "$bname.hp"
+ } else {
+ file copy "[file rootname $test].h" "$bname.hp"
+ }
+ dg-test -keep-output $test $flags "-I."
+ remote_file host delete "$bname.hp"
+ set tmp [ diff "$bname.s" "$bname.s-pch" ]
+ if { $tmp == 0 } {
+ untested "$nshort $flags assembly comparison"
+ } elseif { $tmp == 1 } {
+ pass "$nshort $flags assembly comparison"
+ } else {
+ fail "$nshort $flags assembly comparison"
+ }
+ file delete "$bname.s"
+ file delete "$bname.s-pch"
+ } else {
+ untested "$nshort $flags assembly comparison"
+ }
+
+ } else {
+ untested $nshort
+ untested "$nshort $flags assembly comparison"
+ }
+ }
+}
+
+set dg-do-what-default "$old_dg_do_what_default"
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/gcc.dg/pch/static-1.c b/gcc/testsuite/gcc.dg/pch/static-1.c
new file mode 100644
index 00000000000..c1816e949b4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/static-1.c
@@ -0,0 +1,6 @@
+#include "static-1.hp"
+static int bar(void)
+{
+ static int counter;
+ return counter++;
+}
diff --git a/gcc/testsuite/gcc.dg/pch/static-1.h b/gcc/testsuite/gcc.dg/pch/static-1.h
new file mode 100644
index 00000000000..08cc4395d0e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/static-1.h
@@ -0,0 +1,5 @@
+static int foo(void)
+{
+ static int counter;
+ return counter++;
+}
diff --git a/gcc/testsuite/gcc.dg/pch/static-2.c b/gcc/testsuite/gcc.dg/pch/static-2.c
new file mode 100644
index 00000000000..afda874e279
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/static-2.c
@@ -0,0 +1,6 @@
+#include "static-2.hp"
+int bar(void)
+{
+ static int counter;
+ return counter++;
+}
diff --git a/gcc/testsuite/gcc.dg/pch/static-2.h b/gcc/testsuite/gcc.dg/pch/static-2.h
new file mode 100644
index 00000000000..08cc4395d0e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/static-2.h
@@ -0,0 +1,5 @@
+static int foo(void)
+{
+ static int counter;
+ return counter++;
+}
diff --git a/gcc/testsuite/gcc.dg/pch/system-1.c b/gcc/testsuite/gcc.dg/pch/system-1.c
new file mode 100644
index 00000000000..096fe593e06
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/system-1.c
@@ -0,0 +1,6 @@
+#include "system-1.hp"
+int main(void)
+{
+ puts ("hello world!");
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/pch/system-1.h b/gcc/testsuite/gcc.dg/pch/system-1.h
new file mode 100644
index 00000000000..fbfff34edb0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/system-1.h
@@ -0,0 +1,2 @@
+#include <stdio.h>
+#include <stdlib.h>
diff --git a/gcc/testsuite/lib/g++-dg.exp b/gcc/testsuite/lib/g++-dg.exp
index 8be839e4dcf..2fad5d1f7f8 100644
--- a/gcc/testsuite/lib/g++-dg.exp
+++ b/gcc/testsuite/lib/g++-dg.exp
@@ -37,6 +37,10 @@ proc g++-dg-test { prog do_what extra_tool_flags } {
set compile_type "object"
set output_file "[file rootname [file tail $prog]].o"
}
+ "precompile" {
+ set compile_type "precompiled_header"
+ set output_file "[file tail $prog].pch"
+ }
"link" {
set compile_type "executable"
set output_file "[file rootname [file tail $prog]].exe"
diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp
index 403fefc2f11..dd130b9c37e 100644
--- a/gcc/testsuite/lib/gcc-dg.exp
+++ b/gcc/testsuite/lib/gcc-dg.exp
@@ -69,6 +69,10 @@ proc gcc-dg-test { prog do_what extra_tool_flags } {
set compile_type "object"
set output_file "[file rootname [file tail $prog]].o"
}
+ "precompile" {
+ set compile_type "precompiled_header"
+ set output_file "[file tail $prog].pch"
+ }
"link" {
set compile_type "executable"
set output_file "[file rootname [file tail $prog]].exe"
diff --git a/gcc/toplev.c b/gcc/toplev.c
index ccc061fc740..f98fc366d4a 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -4666,7 +4666,7 @@ init_asm_output (name)
if (!strcmp (asm_file_name, "-"))
asm_out_file = stdout;
else
- asm_out_file = fopen (asm_file_name, "w");
+ asm_out_file = fopen (asm_file_name, "w+");
if (asm_out_file == 0)
fatal_io_error ("can't open %s for writing", asm_file_name);
}
diff --git a/gcc/tree.c b/gcc/tree.c
index 0247bb957dc..f1549ab89db 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -136,8 +136,8 @@ void
init_ttree ()
{
/* Initialize the hash table of types. */
- type_hash_table = htab_create (TYPE_HASH_INITIAL_SIZE, type_hash_hash,
- type_hash_eq, 0);
+ type_hash_table = htab_create_ggc (TYPE_HASH_INITIAL_SIZE, type_hash_hash,
+ type_hash_eq, 0);
}
diff --git a/gcc/tree.h b/gcc/tree.h
index 6075d83b87f..d8bc1a8c72a 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -98,7 +98,7 @@ enum built_in_function
extern const char *const built_in_names[(int) END_BUILTINS];
/* An array of _DECL trees for the above. */
-extern tree built_in_decls[(int) END_BUILTINS];
+extern GTY(()) tree built_in_decls[(int) END_BUILTINS];
/* The definition of tree nodes fills the next several pages. */
@@ -1273,9 +1273,9 @@ struct tree_type GTY(())
tree pointer_to;
tree reference_to;
union tree_type_symtab {
- int address;
+ int GTY ((tag ("0"))) address;
char * GTY ((tag ("1"))) pointer;
- struct die_struct * GTY ((tag ("2"), skip (""))) die;
+ struct die_struct * GTY ((tag ("2"))) die;
} GTY ((desc ("debug_hooks == &sdb_debug_hooks ? 1 : debug_hooks == &dwarf2_debug_hooks ? 2 : 0"),
descbits ("2"))) symtab;
tree name;
@@ -1881,7 +1881,7 @@ struct tree_decl GTY(())
struct function * GTY ((tag ("FUNCTION_DECL"))) f;
rtx GTY ((tag ("PARM_DECL"))) r;
tree GTY ((tag ("FIELD_DECL"))) t;
- int i;
+ int GTY ((tag ("VAR_DECL"))) i;
} GTY ((desc ("TREE_CODE((tree) &(%0))"))) u2;
/* In a FUNCTION_DECL, this is DECL_SAVED_TREE. */
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 948b1a91e3b..673030d5527 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -107,12 +107,12 @@ struct varasm_status GTY(())
/* Number for making the label on the next
constant that is stored in memory. */
-int const_labelno;
+static GTY(()) int const_labelno;
/* Number for making the label on the next
static variable internal to a function. */
-int var_labelno;
+static GTY(()) int var_labelno;
/* Carry information from ASM_DECLARE_OBJECT_NAME
to ASM_FINISH_DECLARE_OBJECT. */
@@ -179,7 +179,7 @@ static bool asm_emit_uninitialised PARAMS ((tree, const char*, int, int));
static void resolve_unique_section PARAMS ((tree, int, int));
static void mark_weak PARAMS ((tree));
-static enum in_section { no_section, in_text, in_data, in_named
+enum in_section { no_section, in_text, in_data, in_named
#ifdef BSS_SECTION_ASM_OP
, in_bss
#endif
@@ -195,7 +195,8 @@ static enum in_section { no_section, in_text, in_data, in_named
#ifdef EXTRA_SECTIONS
, EXTRA_SECTIONS
#endif
-} in_section = no_section;
+};
+static GTY(()) enum in_section in_section = no_section;
/* Return a nonzero value if DECL has a section attribute. */
#ifndef IN_NAMED_SECTION
@@ -205,18 +206,18 @@ static enum in_section { no_section, in_text, in_data, in_named
#endif
/* Text of section name when in_section == in_named. */
-static const char *in_named_name;
+static GTY(()) const char *in_named_name;
/* Hash table of flags that have been used for a particular named section. */
-struct in_named_entry
+struct in_named_entry GTY(())
{
const char *name;
unsigned int flags;
bool declared;
};
-static htab_t in_named_htab;
+static GTY((param_is (struct in_named_entry))) htab_t in_named_htab;
/* Define functions like text_section for any extra sections. */
#ifdef EXTRA_SECTION_FUNCTIONS
@@ -379,7 +380,7 @@ set_named_section_flags (section, flags)
if (!entry)
{
- entry = (struct in_named_entry *) xmalloc (sizeof (*entry));
+ entry = (struct in_named_entry *) ggc_alloc (sizeof (*entry));
*slot = entry;
entry->name = ggc_strdup (section);
entry->flags = flags;
@@ -2119,7 +2120,7 @@ struct rtx_const GTY(())
ENUM_BITFIELD(kind) kind : 16;
ENUM_BITFIELD(machine_mode) mode : 16;
union rtx_const_un {
- REAL_VALUE_TYPE du;
+ REAL_VALUE_TYPE GTY ((tag ("4"))) du;
struct addr_const GTY ((tag ("1"))) addr;
struct rtx_const_u_di {
HOST_WIDE_INT high;
@@ -4703,8 +4704,8 @@ init_varasm_once ()
{
const_str_htab = htab_create_ggc (128, const_str_htab_hash,
const_str_htab_eq, NULL);
- in_named_htab = htab_create (31, in_named_entry_hash,
- in_named_entry_eq, NULL);
+ in_named_htab = htab_create_ggc (31, in_named_entry_hash,
+ in_named_entry_eq, NULL);
const_alias_set = new_alias_set ();
}