OSDN Git Service

Merge from pch-branch.
authorgeoffk <geoffk@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 10 Jan 2003 02:22:34 +0000 (02:22 +0000)
committergeoffk <geoffk@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 10 Jan 2003 02:22:34 +0000 (02:22 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@61136 138bc75d-0d04-0410-961f-82ee72b054a4

130 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/ada/ChangeLog
gcc/ada/ada-tree.h
gcc/ada/gnat_rm.texi
gcc/c-common.c
gcc/c-common.h
gcc/c-decl.c
gcc/c-lex.c
gcc/c-objc-common.c
gcc/c-opts.c
gcc/c-parse.in
gcc/c-pch.c [new file with mode: 0644]
gcc/config/alpha/alpha.c
gcc/config/darwin.c
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/t-rs6000
gcc/cp/ChangeLog
gcc/cp/Make-lang.in
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/g++spec.c
gcc/cp/init.c
gcc/cp/lang-specs.h
gcc/cp/lex.c
gcc/cp/method.c
gcc/cp/optimize.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/repo.c
gcc/cp/search.c
gcc/cp/semantics.c
gcc/cp/tree.c
gcc/cppfiles.c
gcc/cpphash.h
gcc/cpplib.c
gcc/cpplib.h
gcc/cpppch.c [new file with mode: 0644]
gcc/dbxout.c
gcc/doc/cppopts.texi
gcc/doc/gty.texi
gcc/doc/invoke.texi
gcc/doc/passes.texi
gcc/dwarf2asm.c
gcc/dwarf2out.c
gcc/emit-rtl.c
gcc/fold-const.c
gcc/function.c
gcc/gcc.c
gcc/gengtype.c
gcc/ggc-common.c
gcc/ggc-page.c
gcc/ggc-simple.c
gcc/ggc.h
gcc/java/ChangeLog
gcc/java/Make-lang.in
gcc/java/config-lang.in
gcc/java/constants.c
gcc/java/gjavah.c
gcc/java/java-tree.h
gcc/java/jcf-dump.c
gcc/java/jcf-parse.c
gcc/java/jcf-reader.c
gcc/java/jcf.h
gcc/java/lex.c
gcc/java/lex.h
gcc/java/parse.h
gcc/java/parse.y
gcc/mkdeps.c
gcc/mkdeps.h
gcc/objc/objc-act.c
gcc/optabs.h
gcc/stringpool.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/dg.exp
gcc/testsuite/g++.dg/pch/empty.C [new file with mode: 0644]
gcc/testsuite/g++.dg/pch/empty.H [new file with mode: 0644]
gcc/testsuite/g++.dg/pch/pch.exp [new file with mode: 0644]
gcc/testsuite/g++.dg/pch/system-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/pch/system-1.H [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/common-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/common-1.h [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/cpp-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/cpp-1.h [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/cpp-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/cpp-2.h [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/decl-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/decl-1.h [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/decl-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/decl-2.h [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/decl-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/decl-3.h [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/decl-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/decl-4.h [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/decl-5.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/decl-5.h [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/empty.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/empty.h [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/except-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/except-1.h [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/global-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/global-1.h [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/inline-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/inline-1.h [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/inline-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/inline-2.h [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/macro-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/macro-1.h [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/macro-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/macro-2.h [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/macro-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/macro-3.h [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/pch.exp [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/static-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/static-1.h [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/static-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/static-2.h [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/system-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pch/system-1.h [new file with mode: 0644]
gcc/testsuite/lib/g++-dg.exp
gcc/testsuite/lib/gcc-dg.exp
gcc/toplev.c
gcc/tree.c
gcc/tree.h
gcc/varasm.c
include/ChangeLog
include/splay-tree.h

index edae831..2e2e1b2 100644 (file)
@@ -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:
        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>
 
index 5ffdce2..c48d41c 100644 (file)
@@ -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
index 6b435f5..0d06e9c 100644 (file)
@@ -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,
index 53087a7..b1904a4 100644 (file)
@@ -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)"))) 
index dd43cf0..f9c78ce 100644 (file)
@@ -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
index 12cacab..84166c9 100644 (file)
@@ -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;
+\f
 /* 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;
index 4c60d29..3e97662 100644 (file)
@@ -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;
+\f
 /* 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 */
index fde8c48..e3d07aa 100644 (file)
@@ -3226,6 +3226,8 @@ clear_parm_order ()
   current_binding_level->parm_order = NULL_TREE;
 }
 \f
+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;
index 5507e63..a689cca 100644 (file)
@@ -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 ();
 }
index 7d54d7a..c91e635 100644 (file)
@@ -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)
index 85ed5f3..5270d62 100644 (file)
@@ -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;
index 70dfe90..72ca4fe 100644 (file)
@@ -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 (file)
index 0000000..616e002
--- /dev/null
@@ -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);
+}
index ce0810d..dbbf110 100644 (file)
@@ -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 */
 \f
+/* 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);
 }
 \f
-/* 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);
index a7dfe59..bce6d11 100644 (file)
@@ -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 ()
index 6112737..7880cd5 100644 (file)
@@ -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;
 \f
 /* 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"
index 805e15d..c2a7848 100644 (file)
@@ -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
+
index 2970abb..fb53043 100644 (file)
@@ -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.
index b54e3ba..347b71a 100644 (file)
@@ -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 \
index 00458c0..cd93f7b 100644 (file)
@@ -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;
index 845ca19..bace3f4 100644 (file)
@@ -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;
index 8f77d10..aad82c0 100644 (file)
@@ -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));
index 35a14e8..29a7a7f 100644 (file)
@@ -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.  */
index 6363007..2491c8a 100644 (file)
@@ -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;
index 8c1e3ae..75a1d7c 100644 (file)
@@ -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++;
index 2fd0c50..964ee1e 100644 (file)
@@ -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));
index e826467..cf4ca4c 100644 (file)
@@ -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)}\
index 2975399..5749fc4 100644 (file)
@@ -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);
index f4960b2..883a81f 100644 (file)
@@ -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"
 
index fe924f4..8f08c9a 100644 (file)
@@ -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"
index e88045d..629ba5d 100644 (file)
@@ -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;
 }
index 7802e25..e7486af 100644 (file)
@@ -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
index 105e4df..603b04e 100644 (file)
@@ -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);
index 13ed4b0..5e9b395 100644 (file)
@@ -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"
 
index 0aeaa0d..3ed9f2e 100644 (file)
@@ -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.
index 93c62da..a3b6ff1 100644 (file)
@@ -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"
index 4d82196..203619f 100644 (file)
@@ -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)
index 16e8dfe..d5a0b5d 100644 (file)
@@ -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 *));
index e032e75..1019a2a 100644 (file)
@@ -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
index 271a755..bccfecf 100644 (file)
@@ -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 (file)
index 0000000..e7f0c91
--- /dev/null
@@ -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;
+}
index 5fcd28d..480ef82 100644 (file)
@@ -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"
index 74fe8be..95311a8 100644 (file)
@@ -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
index 55deef2..ed7d3d2 100644 (file)
@@ -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
 
index 8b3e365..bfbdd3e 100644 (file)
@@ -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
 
index c47433e..8a96a69 100644 (file)
@@ -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
index 777ba8d..396c2cd 100644 (file)
@@ -688,12 +688,12 @@ dw2_asm_output_delta_sleb128 VPARAMS ((const char *lab1 ATTRIBUTE_UNUSED,
   VA_CLOSE (ap);
 }
 \f
-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"
index c931420..38d3400 100644 (file)
@@ -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
 \f
 /* 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
 \f
 /* 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);
-}
 \f
 /* 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
 
index 0099a50..eb1814a 100644 (file)
@@ -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;
 
index 0c53604..3847fc0 100644 (file)
@@ -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);
     }
 
index 0a0f56d..1c972d2 100644 (file)
@@ -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.  */
index 618d272..8b27a0a 100644 (file)
--- 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;
 
index 855e5ed..b279263 100644 (file)
@@ -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");
 }
 
 \f
@@ -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 ();
 
index f353617..ed6d3b4 100644 (file)
@@ -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 th