summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeoffrey Keating <geoffk@gcc.gnu.org>2003-01-10 02:22:34 +0000
committerGeoffrey Keating <geoffk@gcc.gnu.org>2003-01-10 02:22:34 +0000
commit17211ab55314d76370a68036f2d057b1effd687f (patch)
treea3ff2e89f1924fd7ea1d99358736bc8491352747
parent5f7c78d8a4df096dacfa2d9de367a6174dd631ba (diff)
downloadgcc-17211ab55314d76370a68036f2d057b1effd687f.tar.gz
Merge from pch-branch.
From-SVN: r61136
-rw-r--r--gcc/ChangeLog520
-rw-r--r--gcc/Makefile.in48
-rw-r--r--gcc/ada/ChangeLog6
-rw-r--r--gcc/ada/ada-tree.h3
-rw-r--r--gcc/ada/gnat_rm.texi2
-rw-r--r--gcc/c-common.c10
-rw-r--r--gcc/c-common.h26
-rw-r--r--gcc/c-decl.c8
-rw-r--r--gcc/c-lex.c4
-rw-r--r--gcc/c-objc-common.c5
-rw-r--r--gcc/c-opts.c16
-rw-r--r--gcc/c-parse.in6
-rw-r--r--gcc/c-pch.c226
-rw-r--r--gcc/config/alpha/alpha.c46
-rw-r--r--gcc/config/darwin.c2
-rw-r--r--gcc/config/rs6000/rs6000.c88
-rw-r--r--gcc/config/rs6000/t-rs60005
-rw-r--r--gcc/cp/ChangeLog90
-rw-r--r--gcc/cp/Make-lang.in25
-rw-r--r--gcc/cp/call.c1
-rw-r--r--gcc/cp/class.c133
-rw-r--r--gcc/cp/cp-tree.h27
-rw-r--r--gcc/cp/decl.c3
-rw-r--r--gcc/cp/decl2.c4
-rw-r--r--gcc/cp/g++spec.c96
-rw-r--r--gcc/cp/init.c1
-rw-r--r--gcc/cp/lang-specs.h13
-rw-r--r--gcc/cp/lex.c6
-rw-r--r--gcc/cp/method.c5
-rw-r--r--gcc/cp/optimize.c1
-rw-r--r--gcc/cp/parser.c68
-rw-r--r--gcc/cp/pt.c1
-rw-r--r--gcc/cp/repo.c1
-rw-r--r--gcc/cp/search.c1
-rw-r--r--gcc/cp/semantics.c5
-rw-r--r--gcc/cp/tree.c1
-rw-r--r--gcc/cppfiles.c115
-rw-r--r--gcc/cpphash.h6
-rw-r--r--gcc/cpplib.c84
-rw-r--r--gcc/cpplib.h35
-rw-r--r--gcc/cpppch.c684
-rw-r--r--gcc/dbxout.c139
-rw-r--r--gcc/doc/cppopts.texi11
-rw-r--r--gcc/doc/gty.texi36
-rw-r--r--gcc/doc/invoke.texi134
-rw-r--r--gcc/doc/passes.texi44
-rw-r--r--gcc/dwarf2asm.c38
-rw-r--r--gcc/dwarf2out.c488
-rw-r--r--gcc/emit-rtl.c12
-rw-r--r--gcc/fold-const.c2
-rw-r--r--gcc/function.c2
-rw-r--r--gcc/gcc.c30
-rw-r--r--gcc/gengtype.c1500
-rw-r--r--gcc/ggc-common.c553
-rw-r--r--gcc/ggc-page.c258
-rw-r--r--gcc/ggc-simple.c85
-rw-r--r--gcc/ggc.h184
-rw-r--r--gcc/java/ChangeLog74
-rw-r--r--gcc/java/Make-lang.in8
-rw-r--r--gcc/java/config-lang.in2
-rw-r--r--gcc/java/constants.c64
-rw-r--r--gcc/java/gjavah.c1
-rw-r--r--gcc/java/java-tree.h10
-rw-r--r--gcc/java/jcf-dump.c1
-rw-r--r--gcc/java/jcf-parse.c49
-rw-r--r--gcc/java/jcf-reader.c18
-rw-r--r--gcc/java/jcf.h49
-rw-r--r--gcc/java/lex.c2
-rw-r--r--gcc/java/lex.h7
-rw-r--r--gcc/java/parse.h33
-rw-r--r--gcc/java/parse.y76
-rw-r--r--gcc/mkdeps.c74
-rw-r--r--gcc/mkdeps.h11
-rw-r--r--gcc/objc/objc-act.c1
-rw-r--r--gcc/optabs.h4
-rw-r--r--gcc/stringpool.c93
-rw-r--r--gcc/testsuite/ChangeLog84
-rw-r--r--gcc/testsuite/g++.dg/dg.exp1
-rw-r--r--gcc/testsuite/g++.dg/pch/empty.C5
-rw-r--r--gcc/testsuite/g++.dg/pch/empty.H0
-rw-r--r--gcc/testsuite/g++.dg/pch/pch.exp100
-rw-r--r--gcc/testsuite/g++.dg/pch/system-1.C7
-rw-r--r--gcc/testsuite/g++.dg/pch/system-1.H1
-rw-r--r--gcc/testsuite/gcc.dg/pch/common-1.c3
-rw-r--r--gcc/testsuite/gcc.dg/pch/common-1.h3
-rw-r--r--gcc/testsuite/gcc.dg/pch/cpp-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/pch/cpp-1.h1
-rw-r--r--gcc/testsuite/gcc.dg/pch/cpp-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/pch/cpp-2.h1
-rw-r--r--gcc/testsuite/gcc.dg/pch/decl-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/pch/decl-1.h1
-rw-r--r--gcc/testsuite/gcc.dg/pch/decl-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/pch/decl-2.h3
-rw-r--r--gcc/testsuite/gcc.dg/pch/decl-3.c11
-rw-r--r--gcc/testsuite/gcc.dg/pch/decl-3.h3
-rw-r--r--gcc/testsuite/gcc.dg/pch/decl-4.c9
-rw-r--r--gcc/testsuite/gcc.dg/pch/decl-4.h7
-rw-r--r--gcc/testsuite/gcc.dg/pch/decl-5.c2
-rw-r--r--gcc/testsuite/gcc.dg/pch/decl-5.h1
-rw-r--r--gcc/testsuite/gcc.dg/pch/empty.c8
-rw-r--r--gcc/testsuite/gcc.dg/pch/empty.h0
-rw-r--r--gcc/testsuite/gcc.dg/pch/except-1.c7
-rw-r--r--gcc/testsuite/gcc.dg/pch/except-1.h6
-rw-r--r--gcc/testsuite/gcc.dg/pch/global-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/pch/global-1.h1
-rw-r--r--gcc/testsuite/gcc.dg/pch/inline-1.c10
-rw-r--r--gcc/testsuite/gcc.dg/pch/inline-1.h5
-rw-r--r--gcc/testsuite/gcc.dg/pch/inline-2.c12
-rw-r--r--gcc/testsuite/gcc.dg/pch/inline-2.h5
-rw-r--r--gcc/testsuite/gcc.dg/pch/macro-1.c6
-rw-r--r--gcc/testsuite/gcc.dg/pch/macro-1.h2
-rw-r--r--gcc/testsuite/gcc.dg/pch/macro-2.c8
-rw-r--r--gcc/testsuite/gcc.dg/pch/macro-2.h2
-rw-r--r--gcc/testsuite/gcc.dg/pch/macro-3.c8
-rw-r--r--gcc/testsuite/gcc.dg/pch/macro-3.h2
-rw-r--r--gcc/testsuite/gcc.dg/pch/pch.exp100
-rw-r--r--gcc/testsuite/gcc.dg/pch/static-1.c6
-rw-r--r--gcc/testsuite/gcc.dg/pch/static-1.h5
-rw-r--r--gcc/testsuite/gcc.dg/pch/static-2.c6
-rw-r--r--gcc/testsuite/gcc.dg/pch/static-2.h5
-rw-r--r--gcc/testsuite/gcc.dg/pch/system-1.c6
-rw-r--r--gcc/testsuite/gcc.dg/pch/system-1.h2
-rw-r--r--gcc/testsuite/lib/g++-dg.exp4
-rw-r--r--gcc/testsuite/lib/gcc-dg.exp4
-rw-r--r--gcc/toplev.c2
-rw-r--r--gcc/tree.c4
-rw-r--r--gcc/tree.h8
-rw-r--r--gcc/varasm.c23
-rw-r--r--include/ChangeLog8
-rw-r--r--include/splay-tree.h25
130 files changed, 5507 insertions, 1560 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index edae8315f57..2e2e1b2ac32 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,519 @@
+2003-01-09 Geoffrey Keating <geoffk@apple.com>
+
+ Merge from pch-branch:
+
+ 2003-01-06 Geoffrey Keating <geoffk@apple.com>
+
+ * ggc-page.c (ggc_pch_read): Update the statistics after a PCH
+ load.
+
+ 2002-12-24 Geoffrey Keating <geoffk@apple.com>
+
+ * cpplib.c (count_registered_pragmas): New function.
+ (save_registered_pragmas): New function.
+ (_cpp_save_pragma_names): New function.
+ (restore_registered_pragmas): New function.
+ (_cpp_restore_pragma_names): New function.
+ * cpphash.h (_cpp_save_pragma_names): Prototype.
+ (_cpp_restore_pragma_names): Likewise.
+ * cpppch.c (struct save_macro_item): Split from save_macro_data.
+ (struct save_macro_data): New field 'saved_pragmas'.
+ (save_macros): Update for changes to struct save_macro_data.
+ (cpp_prepare_state): Call _cpp_save_pragma_names, update
+ for changes to struct save_macro_data.
+ (cpp_read_state): Call _cpp_restore_pragma_names, update
+ for changes to struct save_macro_data.
+
+ * cpppch.c (cpp_read_state): Restore the hashtable references
+ in the cpp_reader.
+
+ * tree.h (built_in_decls): Mark for PCH.
+
+ * dbxout.c (lastfile): Don't mark for PCH.
+
+ * ggc.h: Document PCH calls into memory managers.
+
+ 2002-12-18 Geoffrey Keating <geoffk@apple.com>
+
+ * doc/invoke.texi (Precompiled Headers): Document the
+ directory form of PCH.
+ * cppfiles.c (validate_pch): New function.
+ (open_file_pch): Search suitably-named directories for PCH files.
+
+ 2002-12-14 Geoffrey Keating <geoffk@apple.com>
+
+ * doc/gty.texi (GTY Options): Document chain_next, chain_prev,
+ reorder options.
+ (Type Information): Mention that the information is also
+ used to implement PCH.
+ * doc/passes.texi (Passes): Improve documentation of
+ language-specific files.
+
+ 2002-12-11 Geoffrey Keating <geoffk@apple.com>
+
+ * gengtype.c (struct write_types_data): Add reorder_note_routine field.
+ (struct walk_type_data): Add reorder_fn field.
+ (walk_type): Process 'reorder' option.
+ (write_types_process_field): Reorder parameters to gt_pch_note_object,
+ call reorder_note_routine.
+ (write_func_for_structure): Reorder parameters to gt_pch_note_object.
+ (ggc_wtd): Update for change to struct write_types_data.
+ (pch_wtd): Likewise.
+ * ggc.h (gt_pch_note_object): Reorder parameters.
+ (gt_handle_reorder): New definition.
+ (gt_pch_note_reorder): New prototype.
+ * ggc-common.c (struct ptr_data): Add reorder_fn.
+ (gt_pch_note_object): Reorder parameters.
+ (gt_pch_note_reorder): New.
+ (gt_pch_save): Call reorder_fn.
+ * stringpool.c (gt_pch_n_S): Update for change to gt_pch_note_object.
+
+ * dbxout.c (cwd): Don't mark for PCH.
+
+ 2002-12-09 Geoffrey Keating <geoffk@apple.com>
+
+ * gengtype.c (finish_root_table): Fix some warnings.
+ (write_root): Handle TYPE_STRING.
+ * ggc.h (gt_ggc_m_S): Add prototype.
+ * stringpool.c (gt_ggc_m_S): New function.
+
+ 2002-11-30 Geoffrey Keating <geoffk@apple.com>
+
+ * dwarf2out.c (dw2_string_counter): New.
+ (AT_string_form): Use it.
+ (same_dw_val_p): Update for removal of hashtable.h hash tables.
+
+ 2002-11-22 Geoffrey Keating <geoffk@apple.com>
+
+ * dbxout.c: Include gt-dbxout.h.
+ (lastfile): Mark for PCH/GGC.
+ (cwd): Likewise.
+ (struct typeinfo): Likewise.
+ (typevec): Likewise.
+ (typevec_len): Likewise.
+ (next_type_number): Likewise.
+ (struct dbx_file): Likewise.
+ (current_file): Likewise.
+ (next_file_number): Likewise.
+ (dbxout_init): Allocate typevec, struct dbx_file with GGC.
+ (dbxout_start_source_file): Allocate struct dbx_file with GGC.
+ (dbxout_end_source_file): Don't free struct dbx_file.
+ (dbxout_type): Use GGC to allocate typevec.
+ * Makefile.in (dbxout.o): Depend on gt-dbxout.h, $(GGC_H).
+ (GTFILES): Add dbxout.c.
+ (gt-dbxout.h): New rule.
+
+ * Makefile.in (c-pch.o): Add debug.h as dependency.
+ * c-pch.c: Include debug.h.
+ (pch_init): Call start_source_file to keep nesting right.
+ (c_common_read_pch): Add orig_name parameter. Call
+ start_source_file debug hook. Call end_source_file debug hook.
+ * c-common.h (c_common_read_pch): Update prototype.
+ * cpplib.h (struct cpp_callbacks): Add fourth field to read_pch
+ callback.
+ * cppfiles.c (struct include_file): Add new field `header_name'.
+ (find_or_create_entry): Default it to `name'.
+ (open_file_pch): Set it to the original header file searched for.
+ (stack_include_file): Don't stack an empty buffer, just handle
+ PCH files immediately. Pass header_name field to read_pch callback.
+
+ 2002-11-19 Geoffrey Keating <geoffk@apple.com>
+
+ * function.c (funcdef_no): Mark to be saved in a PCH.
+
+ 2002-11-15 Geoffrey Keating <geoffk@apple.com>
+
+ * ggc-page.c (ggc_pch_read): Remove unused 'bmap_size'.
+
+ * cpppch.c (cpp_read_state): Correct size reallocated for 'defn'.
+
+ 2002-11-14 Geoffrey Keating <geoffk@apple.com>
+
+ * optabs.h (code_to_optab): Add GTY marker.
+
+ 2002-11-13 Geoffrey Keating <geoffk@apple.com>
+
+ * Makefile.in (GTFILES): Add cpplib.h.
+ * c-common.h (struct c_common_identifier): Don't skip 'node' field.
+ * c-decl.c (build_compound_literal): Don't use var_labelno.
+ * cpplib.h (struct cpp_hashnode): Use gengtype to mark.
+ * dwarf2asm.c (dw2_force_const_mem): Don't use const_labelno.
+ * varasm.c (const_labelno): Use gengtype to mark.
+ (var_labelno): Likewise.
+ (in_section): Likewise.
+ (in_named_name): Likewise.
+ (struct in_named_entry): Likewise.
+ (in_named_htab): Likewise.
+ (set_named_section_flags): Use GGC to allocate struct in_named_entry.
+ (init_varasm_once): Use GGC to allocate in_named_htab.
+ * config/darwin.c (current_pic_label_num): Mark for PCH.
+
+ 2002-11-11 Geoffrey Keating <geoffk@apple.com>
+
+ * ggc-simple.c (init_ggc_pch): New stub procedure.
+ (ggc_pch_count_object): Likewise.
+ (ggc_pch_total_size): Likewise.
+ (ggc_pch_this_base): Likewise.
+ (ggc_pch_alloc_object): Likewise.
+ (ggc_pch_prepare_write): Likewise.
+ (ggc_pch_write_object): Likewise
+ (ggc_pch_finish): Likewise.
+ (ggc_pch_read): Likewise.
+
+ 2002-11-08 Geoffrey Keating <geoffk@apple.com>
+
+ * c-pch.c (c_common_write_pch): Write the macro definitions after
+ the GCed data.
+ (c_common_read_pch): Call cpp_prepare_state. Restore the macro
+ definitions after the GCed data.
+ * cpplib.c (save_macros): New.
+ (reset_ht): New.
+ (cpp_write_pch_deps): Split out of cpp_write_pch.
+ (cpp_write_pch_state): Split out of cpp_write_pch.
+ (cpp_write_pch): Delete.
+ (struct save_macro_data): Delete.
+ (cpp_prepare_state): New.
+ (cpp_read_state): Erase and restore initial macro definitions.
+ * cpplib.h (struct save_macro_data): Forward-declare.
+ (cpp_write_pch_deps): Prototype.
+ (cpp_write_pch_state): Prototype.
+ (cpp_write_pch): Delete prototype.
+ (cpp_prepare_state): Prototype.
+ (cpp_read_state): Add fourth argument.
+
+ 2002-11-04 Geoffrey Keating <geoffk@apple.com>
+
+ * gengtype.c (adjust_field_rtx_def): Don't use skip on valid fields.
+ (write_array): Remove warning.
+
+ * gengtype.c (contains_scalar_p): New.
+ (finish_root_table): Add the table to all languages, even if it's
+ empty.
+ (write_roots): Output gt_pch_scalar_rtab.
+ * ggc-common.c (gt_pch_save): Write out scalars.
+ (gt_pch_restore): Read scalars back.
+
+ * ggc-page.c (OBJECTS_IN_PAGE): New macro.
+ (struct page_entry): Delete pch_page field.
+ (ggc_recalculate_in_use_p): Use OBJECTS_IN_PAGE.
+ (clear_marks): Likewise.
+ (sweep_pages): Likewise.
+ (poison_pages): Likewise.
+ (ggc_print_statistics): Likewise.
+ (ggc_pch_read): Don't free objects read from a PCH.
+ Properly set up in_use_p and page_tails.
+
+ 2002-10-25 Geoffrey Keating <geoffk@apple.com>
+
+ * gengtype.c (struct write_types_data): New.
+ (struct walk_type_data): Make `cookie' const; add extra
+ prev_val item; add `orig_s' field.
+ (walk_type): Update prev_val[3].
+ (write_types_process_field): New.
+ (write_func_for_structure): Take write_types_data structure.
+ (write_types): New.
+ (ggc_wtd): New.
+ (pch_wtd): New.
+ (write_types_local_process_field): New.
+ (gc_mark_process_field): Delete.
+ (write_local_func_for_structure): New.
+ (gc_mark_func_name): Delete.
+ (write_gc_types): Delete.
+ (write_local): New.
+ (finish_root_table): Don't include 'ggc_' in PFX.
+ (write_root): Rename from write_root. Fill pchw field of structures.
+ (write_array): New.
+ (write_roots): Rename from write_gc_roots. Split out to write_array.
+ Update to changes to other routines. Write gt_pch_cache_rtab table.
+ (main): Write PCH walking routines.
+ * ggc-common.c: Include toplev.h, sys/mman.h.
+ (ggc_mark_roots): For cache hashtables, also mark the hash table
+ and the array of entries.
+ (saving_htab): New.
+ (struct ptr_data): New.
+ (POINTER_HASH): New.
+ (gt_pch_note_object): New.
+ (saving_htab_hash): New.
+ (saving_htab_eq): New.
+ (struct traversal_state): New.
+ (call_count): New.
+ (call_alloc): New.
+ (compare_ptr_data): New.
+ (relocate_ptrs): New.
+ (write_pch_globals): New.
+ (struct mmap_info): New.
+ (gt_pch_save): New.
+ (gt_pch_restore): New.
+ * ggc-page.c (ROUND_UP_VALUE): New.
+ (ROUND_UP): New.
+ (struct page_entry): Add field `pch_page'.
+ (init_ggc): Use ROUND_UP.
+ (struct ggc_pch_data): Declare.
+ (init_ggc_pch): New.
+ (ggc_pch_count_object): New.
+ (ggc_pch_total_size): New.
+ (ggc_pch_this_base): New.
+ (ggc_pch_alloc_object): New.
+ (ggc_pch_prepare_write): New.
+ (ggc_pch_write_object): New.
+ (ggc_pch_finish): New.
+ (ggc_pch_read): New.
+ * ggc.h (gt_pointer_operator): New.
+ (gt_note_pointers): New.
+ (gt_pch_note_object): New prototype.
+ (gt_pointer_walker): New.
+ (struct ggc_root_tab): Use gt_pointer_walker, add `pchw' field.
+ (LAST_GGC_ROOT_TAB): Update.
+ (gt_pch_cache_rtab): Declare.
+ (gt_pch_scalar_rtab): Declare.
+ (struct ggc_cache_tab): Use gt_pointer_walker, add `pchw' field.
+ (LAST_GGC_CACHE_TAB): Update.
+ (gt_pch_save_stringpool): Declare.
+ (gt_pch_restore_stringpool): Declare.
+ (gt_pch_p_S): Declare.
+ (gt_pch_n_S): Declare.
+ (struct ggc_pch_data): Forward-declare.
+ (init_ggc_pch): Declare.
+ (ggc_pch_count_object): Declare.
+ (ggc_pch_total_size): Declare.
+ (ggc_pch_this_base): Declare.
+ (ggc_pch_alloc_object): Declare.
+ (ggc_pch_prepare_write): Declare.
+ (ggc_pch_write_object): Declare.
+ (ggc_pch_finish): Declare.
+ (ggc_pch_read): Declare.
+ (gt_pch_save): Declare.
+ (gt_pch_restore): Declare.
+ * fold-const.c (size_int_type_wide): Allocate size_htab using GGC.
+ * emit-rtl.c (init_emit_once): Allocate const_int_htab,
+ const_double_htab, mem_attrs_htab using GGC.
+ * c-pch.c: Include ggc.h.
+ (pch_init): Allow reading PCH file back.
+ (c_common_write_pch): Call gt_pch_save.
+ (c_common_read_pch): Call gt_pch_restore.
+ * c-parse.in (init_reswords): Delete now-untrue comment.
+ Allocate ridpointers using GGC.
+ * c-objc-common.c (c_objc_common_finish_file): Write PCH before
+ calling expand_deferred_fns.
+ * c-common.h (ridpointers): Mark for GTY machinery.
+ * Makefile.in (stringpool.o): Update dependencies.
+ (c-pch.o): Update dependencies.
+ (ggc-common.o): Update dependencies.
+ * stringpool.c: Include gt-stringpool.h.
+ (gt_pch_p_S): New.
+ (gt_pch_n_S): New.
+ (struct string_pool_data): New.
+ (spd): New.
+ (gt_pch_save_stringpool): New.
+ (gt_pch_restore_stringpool): New.
+ * tree.c (init_ttree): Make type_hash_table allocated using GC.
+
+ 2002-10-04 Geoffrey Keating <geoffk@apple.com>
+
+ * gengtype.c (adjust_field_rtx_def): Don't pass size_t to printf.
+ (output_mangled_typename): Don't pass size_t to printf.
+
+ * tree.h (union tree_type_symtab): Add tag to `address' field.
+ (union tree_decl_u2): Add tag to 'i' field.
+ * varasm.c (union rtx_const_un): Add tags to all fields.
+ * gengtype.c (struct walk_type_data): New.
+ (output_escaped_param): Take struct walk_type_data parameter.
+ (write_gc_structure_fields): Delete.
+ (walk_type): New.
+ (write_gc_marker_routine_for_structure): Delete.
+ (write_func_for_structure): New.
+ (gc_mark_process_field): New.
+ (gc_mark_func_name): New.
+ (gc_counter): Delete.
+ (write_gc_types): Use write_func_for_structure.
+ (write_gc_roots): Use walk_type.
+
+ 2002-10-02 Geoffrey Keating <geoffk@apple.com>
+
+ * ggc-common.c (ggc_mark_roots): Delete 'x'.
+ (ggc_splay_dont_free): Fix warning about unused 'x'.
+ (ggc_print_common_statistics): Remove warnings.
+
+ 2002-10-01 Mike Stump <mrs@apple.com>
+
+ * ggc-common.c (ggc_splay_alloc): Actually return the allocated area.
+ * gengtype.c (write_gc_structure_fields): Handle param[digit]_is.
+
+ 2002-09-01 Geoffrey Keating <geoffk@redhat.com>
+ Catherine Moore <clm@redhat.com>
+
+ * Makefile (c-pch.o): Update dependencies.
+ (LIBCPP_OBJS): Add cpppch.o.
+ (cpppch.o): New.
+ * c-common.c (c_common_init): Don't call pch_init here.
+ * c-common.h (c_common_read_pch): Update prototype.
+ * c-lex.c (c_common_parse_file): Call pch_init here.
+ * c-opts.c (COMMAND_LINE_OPTIONS): Add -Winvalid-pch, -fpch-deps.
+ (c_common_decode_option): Handle them.
+ * c-pch.c: Include c-pragma.h.
+ (save_asm_offset): Delete.
+ (pch_init): Move contents of save_asm_offset into here, call
+ cpp_save_state.
+ (c_common_write_pch): Call cpp_write_pch.
+ (c_common_valid_pch): Warn only when -Winvalid-pch. Call
+ cpp_valid_state.
+ (c_common_read_pch): Add NAME parameter. Call cpp_read_state.
+ * cppfiles.c (stack_include_file): Update for change to
+ parameters of cb.read_pch.
+ * cpphash.h (struct cpp_reader): Add `savedstate' field.
+ * cpplib.h (struct cpp_options): Add `warn_invalid_pch' and
+ `restore_pch_deps' fields.
+ (struct cpp_callbacks): Add NAME parameter to `read_pch'.
+ (cpp_save_state): Prototype.
+ (cpp_write_pch): Prototype.
+ (cpp_valid_state): Prototype.
+ (cpp_read_state): Prototype.
+ * cpppch.c: New file.
+ * flags.h (version_flag): Remove prototype.
+ * mkdeps.c (deps_save): New.
+ (deps_restore): New.
+ * mkdeps.h (deps_save): Prototype.
+ (deps_restore): Prototype.
+ * toplev.c (late_init_hook): Delete.
+ (version_flag): Make static again.
+ (compile_file): Don't call late_init_hook.
+ * toplev.h (late_init_hook): Delete.
+ * doc/cppopts.texi: Document -fpch-deps.
+ * doc/invoke.texi (Warning Options): Document -Winvalid-pch.
+
+ 2002-08-27 Geoffrey Keating <geoffk@redhat.com>
+
+ * c-pch.c (c_common_write_pch): Rename from c_write_pch, change
+ callers.
+ (c_common_valid_pch): Rename from c_valid_pch, change callers.
+ (c_common_read_pch): Rename from c_read_pch, change callers.
+
+ * c-opts.c (COMMAND_LINE_OPTIONS): Allow -output-pch= to have
+ a space between it and its argument.
+
+ 2002-08-24 Geoffrey Keating <geoffk@redhat.com>
+
+ * c-pch.c: New file.
+ * toplev.h (late_init_hook): Declare.
+ * toplev.c (late_init_hook): Define.
+ (version_flag): Make globally visible.
+ (compile_file): Call late_init_hook.
+ (init_asm_output): Make output file seekable.
+ * gcc.c (default_compilers): Update c-header rule.
+ * flags.h (version_flag): Declare.
+ * cpplib.h (struct cpp_callbacks): Add 'valid_pch' and 'read_pch'
+ fields.
+ * cppfiles.c (struct include_file): Add 'pch' field.
+ (INCLUDE_PCH_P): New.
+ (open_file_pch): New.
+ (stack_include_file): Handle PCH files specially.
+ (find_include_file): Call open_file_pch instead of open_file.
+ (_cpp_read_file): Explain why open_file is used instead of
+ open_file_pch.
+ * c-opts.c (c_common_decode_option): Correct OPT__output_pch case.
+ * c-objc-common.c (c_objc_common_finish_file): Call c_write_pch.
+ * c-lex.c (init_c_lex): Set valid_pch and read_pch fields
+ in cpplib callbacks.
+ * c-common.c (pch_file): Correct comment.
+ (allow_pch): Define.
+ (c_common_init): Call pch_init.
+ * c-common.h (allow_pch): Declare.
+ (pch_init): Declare.
+ (c_valid_pch): Declare.
+ (c_read_pch): Declare.
+ (c_write_pch): Declare.
+ * Makefile.in (c-pch.o): New.
+ (C_AND_OBJC_OBJS): Add c-pch.o.
+ * doc/invoke.texi (Precompiled Headers): Add index entries,
+ complete truncated paragraph.
+
+ 2002-08-17 Geoffrey Keating <geoffk@redhat.com>
+
+ * c-common.c: (pch_file): Define.
+ * c-common.h (pch_file): Declare.
+ * c-opts.c (COMMAND_LINE_OPTIONS): Add --output-pch=.
+ (missing_arg): Require --output-pch= to have an argument.
+ (c_common_decode_option): Handle --output-pch=.
+ * gcc.c: Document new %V.
+ (default_compilers): Handle compiling C header files.
+ (do_spec_1): Implement %V.
+ (main): Handle "gcc foo.h" without trying to run linker.
+ * doc/invoke.texi (Invoking GCC): Add new menu item for PCH.
+ (Overall Options): Document what the driver does with header files,
+ document new -x option possibilities.
+ (Invoking G++): More documentation for PCH.
+ (Precompiled Headers): New.
+
+ 2002-08-09 Geoffrey Keating <geoffk@redhat.com>
+
+ * ggc.h: Don't include varray.h. Rearrange functions to be more
+ organized.
+ (ggc_add_root): Delete.
+ (ggc_mark_rtx): Delete.
+ (ggc_mark_tree): Delete.
+ (struct ggc_statistics): Remove contents.
+ * ggc-common.c: Remove unneeded includes.
+ (struct ggc_root): Delete.
+ (roots): Delete.
+ (ggc_add_root): Delete.
+ (ggc_mark_roots): Don't mark `roots'. Call ggc_mark_stringpool.
+ (ggc_print_common_statistics): Remove most of the contents.
+ * Makefile.in (GGC_H): No longer uses varray.h.
+ (ggc-common.o): Update dependencies.
+ (c-parse.o): Add varray.h to dependencies.
+ (c-common.o): Add varray.h.
+ * stringpool.c (mark_ident): Use mangled name for tree marker routine.
+ (mark_ident_hash): Rename to ggc_mark_stringpool.
+ (init_stringpool): Don't use ggc_add_root.
+ * c-parse.in: Include varray.h.
+ * c-common.c: Include varray.h.
+ * objc/Make-lang.in (objc-act.o): Add varray.h.
+ * objc/objc-act.c: Include varray.h.
+
+ 2002-07-25 Geoffrey Keating <geoffk@redhat.com>
+
+ * dwarf2out.c (dw_cfi_oprnd2_desc): Fix ISO-only function definition.
+ (dw_cfi_oprnd1_desc): Likewise.
+
+ 2002-07-17 Geoffrey Keating <geoffk@redhat.com>
+
+ * config/alpha/alpha.c (struct alpha_links): Use gengtype to mark;
+ move out of ifdef.
+ (alpha_links): Use gengtype to mark; move out of ifdef.
+ (mark_alpha_links_node): Delete.
+ (mark_alpha_links): Delete.
+ (alpha_need_linkage): Use GGC to allocate splay tree, struct
+ alpha_links, strings. Don't use ggc_add_root.
+ * ggc-common.c (ggc_splay_alloc): New.
+ (ggc_splay_dont_free): New.
+ * ggc.h (ggc_mark_rtx): Update for changed name mangling.
+ (ggc_mark_tree): Likewise.
+ (splay_tree_new_ggc): New.
+ (ggc_splay_alloc): Declare.
+ (ggc_splay_dont_free): Declare.
+ * dwarf2asm.c: Include gt-dwarf2asm.h.
+ (mark_indirect_pool_entry): Delete.
+ (mark_indirect_pool): Delete.
+ (indirect_pool): Use gengtype to mark.
+ (dw2_force_const_mem): Don't use ggc_add_root.
+ * Makefile.in (dwarf2asm.o): Depend on gt-dwarf2asm.h.
+ (GTFILES): Add SPLAY_TREE_H, dwarf2asm.c.
+ (gt-dwarf2asm.h): Depend on s-gtype.
+
+ 2002-07-08 Geoffrey Keating <geoffk@redhat.com>
+
+ * tree.h (union tree_type_symtab): Mark `die' field.
+ * Makefile.in (dwarf2out.o): Update dependencies.
+ * dwarf2out.c: Use GGC to allocate all structures. Convert to htab_t
+ hash tables.
+ (dw_cfi_oprnd1_desc): New function.
+ (dw_cfi_oprnd2_desc): New function.
+ (indirect_string_alloc): Delete.
+ (debug_str_do_hash): New function.
+ (debug_str_eq): New function.
+ (mark_limbo_die_list): Delete.
+ (dwarf2out_init): Don't call ggc_add_root.
+
2003-01-09 Vladimir Makarov <vmakarov@redhat.com>
The following changes are merged from itanium-sched-branch:
@@ -438,10 +954,10 @@
the generated code.
(write_automata): Call the new function.
-
Thu Jan 9 22:47:38 CET 2003 Jan Hubicka <jh@suse.cz>
- * i386.md (unit, prefix_0f, memory attributes): Hanlde sseicvt correctly.
+ * i386.md (unit, prefix_0f, memory attributes): Hanlde sseicvt
+ correctly.
2003-01-09 Paolo Carlini <pcarlini@unitus.it>
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 5ffdce2a9fb..c48d41cc3a2 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -587,7 +587,7 @@ REGS_H = regs.h varray.h $(MACHMODE_H)
INTEGRATE_H = integrate.h varray.h
LOOP_H = loop.h varray.h bitmap.h
GCC_H = gcc.h version.h
-GGC_H = ggc.h varray.h gtype-desc.h
+GGC_H = ggc.h gtype-desc.h
TIMEVAR_H = timevar.h timevar.def
INSN_ATTR_H = insn-attr.h $(srcdir)/insn-addr.h $(srcdir)/varray.h
C_COMMON_H = c-common.h $(SPLAY_TREE_H) $(CPPLIB_H)
@@ -739,7 +739,7 @@ CXX_TARGET_OBJS=@cxx_target_objs@
# Language-specific object files for C and Objective C.
C_AND_OBJC_OBJS = attribs.o c-errors.o c-lex.o c-pragma.o c-decl.o c-typeck.o \
c-convert.o c-aux-info.o c-common.o c-opts.o c-format.o c-semantics.o \
- c-objc-common.o c-dump.o libcpp.a $(C_TARGET_OBJS)
+ c-objc-common.o c-dump.o c-pch.o libcpp.a $(C_TARGET_OBJS)
# Language-specific object files for C.
C_OBJS = c-parse.o c-lang.o c-pretty-print.o $(C_AND_OBJC_OBJS)
@@ -1175,7 +1175,7 @@ c-errors.o: c-errors.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(C_TREE_H) flags.h diagnostic.h $(TM_P_H)
c-parse.o : $(srcdir)/c-parse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(GGC_H) intl.h $(C_TREE_H) input.h flags.h toplev.h output.h $(CPPLIB_H) \
- gt-c-parse.h
+ varray.h gt-c-parse.h
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-c $(srcdir)/c-parse.c $(OUTPUT_OPTION)
@@ -1246,7 +1246,7 @@ tlink.o: tlink.c $(DEMANGLE_H) $(HASHTAB_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h
c-common.o : c-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(OBSTACK_H) $(C_COMMON_H) flags.h toplev.h output.h c-pragma.h $(RTL_H) \
$(GGC_H) $(EXPR_H) $(TM_P_H) builtin-types.def builtin-attrs.def $(TARGET_H) \
- diagnostic.h except.h gt-c-common.h real.h langhooks.h
+ diagnostic.h except.h gt-c-common.h real.h langhooks.h varray.h
c-pretty-print.o : c-pretty-print.c c-pretty-print.h pretty-print.h \
$(C_COMMON_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) real.h
@@ -1270,6 +1270,9 @@ c-semantics.o : c-semantics.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE
c-dump.o : c-dump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(C_TREE_H) tree-dump.h
+c-pch.o : c-pch.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(CPPLIB_H) $(TREE_H) \
+ c-common.h output.h toplev.h c-pragma.h $(GGC_H) debug.h
+
# Language-independent files.
DRIVER_DEFINES = \
@@ -1349,18 +1352,17 @@ gtype-desc.o: gtype-desc.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) varray.h
libfuncs.h debug.h $(GGC_H) bitmap.h $(BASIC_BLOCK_H) hard-reg-set.h \
ssa.h cselib.h insn-addr.h
-ggc-common.o: ggc-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
- flags.h $(GGC_H) varray.h $(HASHTAB_H) $(TM_P_H) langhooks.h \
- $(PARAMS_H)
+ggc-common.o: ggc-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(GGC_H) \
+ $(HASHTAB_H) toplev.h
ggc-simple.o: ggc-simple.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
flags.h $(GGC_H) varray.h $(TIMEVAR_H) $(TM_P_H) $(PARAMS_H)
ggc-page.o: ggc-page.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
- flags.h toplev.h $(GGC_H) varray.h $(TIMEVAR_H) $(TM_P_H)
+ flags.h toplev.h $(GGC_H) varray.h $(TIMEVAR_H) $(TM_P_H) $(PARAMS_H)
-stringpool.o: stringpool.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- $(OBSTACK_H) flags.h toplev.h $(GGC_H)
+stringpool.o: stringpool.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(TREE_H) $(GGC_H) gt-stringpool.h
hashtable.o: hashtable.c hashtable.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(OBSTACK_H)
@@ -1466,11 +1468,12 @@ optabs.o : optabs.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_
toplev.h $(GGC_H) real.h $(TM_P_H) except.h gt-optabs.h $(BASIC_BLOCK_H)
dbxout.o : dbxout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) \
flags.h $(REGS_H) debug.h $(TM_P_H) $(TARGET_H) function.h langhooks.h \
- insn-config.h reload.h gstab.h xcoffout.h output.h dbxout.h toplev.h
+ insn-config.h reload.h gstab.h xcoffout.h output.h dbxout.h toplev.h \
+ $(GGC_H) gt-dbxout.h
debug.o : debug.c debug.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H)
sdbout.o : sdbout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) \
flags.h function.h $(EXPR_H) output.h hard-reg-set.h $(REGS_H) real.h \
- insn-config.h xcoffout.h c-pragma.h ggc.h $(TARGET_H) \
+ insn-config.h xcoffout.h c-pragma.h $(GGC_H) $(TARGET_H) \
sdbout.h toplev.h $(TM_P_H) except.h debug.h langhooks.h gt-sdbout.h
dwarfout.o : dwarfout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(RTL_H) dwarf.h flags.h insn-config.h reload.h output.h toplev.h $(TM_P_H) \
@@ -1480,7 +1483,7 @@ dwarf2out.o : dwarf2out.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H)
hard-reg-set.h $(REGS_H) $(EXPR_H) libfuncs.h toplev.h dwarf2out.h varray.h \
$(GGC_H) except.h dwarf2asm.h $(TM_P_H) langhooks.h $(HASHTAB_H) gt-dwarf2out.h
dwarf2asm.o : dwarf2asm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) flags.h $(RTL_H) \
- $(TREE_H) output.h dwarf2asm.h $(TM_P_H) $(GGC_H)
+ $(TREE_H) output.h dwarf2asm.h $(TM_P_H) $(GGC_H) gt-dwarf2asm.h
vmsdbgout.o : vmsdbgout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(RTL_H) flags.h output.h vmsdbg.h debug.h langhooks.h function.h $(TARGET_H)
xcoffout.o : xcoffout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) \
@@ -1862,22 +1865,22 @@ s-preds: genpreds$(build_exeext) $(srcdir)/move-if-change
$(SHELL) $(srcdir)/move-if-change tmp-preds.h tm-preds.h
$(STAMP) s-preds
-GTFILES = $(srcdir)/location.h $(srcdir)/coretypes.h \
- $(host_xm_file_list) $(tm_file_list) $(HASHTAB_H) \
+GTFILES = $(srcdir)/location.h $(srcdir)/coretypes.h $(srcdir)/cpplib.h \
+ $(host_xm_file_list) $(tm_file_list) $(HASHTAB_H) $(SPLAY_TREE_H) \
$(srcdir)/bitmap.h $(srcdir)/function.h $(srcdir)/rtl.h $(srcdir)/optabs.h \
$(srcdir)/tree.h $(srcdir)/libfuncs.h $(srcdir)/hashtable.h $(srcdir)/real.h \
$(srcdir)/varray.h $(srcdir)/ssa.h $(srcdir)/insn-addr.h $(srcdir)/cselib.h \
+ $(srcdir)/basic-block.h $(srcdir)/location.h \
$(srcdir)/c-common.h $(srcdir)/c-tree.h \
- $(srcdir)/basic-block.h \
$(srcdir)/alias.c $(srcdir)/bitmap.c $(srcdir)/cselib.c \
- $(srcdir)/dwarf2out.c $(srcdir)/emit-rtl.c \
- $(srcdir)/except.c $(srcdir)/explow.c $(srcdir)/expr.c \
+ $(srcdir)/dbxout.c $(srcdir)/dwarf2out.c $(srcdir)/dwarf2asm.c \
+ $(srcdir)/emit-rtl.c $(srcdir)/except.c $(srcdir)/explow.c $(srcdir)/expr.c \
$(srcdir)/fold-const.c $(srcdir)/function.c \
$(srcdir)/gcse.c $(srcdir)/integrate.c $(srcdir)/lists.c $(srcdir)/optabs.c \
$(srcdir)/profile.c $(srcdir)/ra-build.c $(srcdir)/regclass.c \
$(srcdir)/reg-stack.c \
$(srcdir)/sdbout.c $(srcdir)/stmt.c $(srcdir)/stor-layout.c \
- $(srcdir)/tree.c $(srcdir)/varasm.c \
+ $(srcdir)/stringpool.c $(srcdir)/tree.c $(srcdir)/varasm.c \
$(out_file) \
@all_gtfiles@
@@ -1891,9 +1894,9 @@ gt-integrate.h gt-stmt.h gt-tree.h gt-varasm.h gt-emit-rtl.h : s-gtype; @true
gt-explow.h gt-stor-layout.h gt-regclass.h gt-lists.h : s-gtype; @true
gt-alias.h gt-cselib.h gt-fold-const.h gt-gcse.h gt-profile.h : s-gtype; @true
gt-expr.h gt-sdbout.h gt-optabs.h gt-bitmap.h gt-dwarf2out.h : s-gtype ; @true
-gt-ra-build.h gt-reg-stack.h : s-gtype ; @true
+gt-ra-build.h gt-reg-stack.h gt-dwarf2asm.h gt-dbxout.h : s-gtype ; @true
gt-c-common.h gt-c-decl.h gt-c-parse.h gt-c-pragma.h : s-gtype; @true
-gt-c-objc-common.h gtype-c.h gt-location.h : s-gtype ; @true
+gt-c-objc-common.h gtype-c.h gt-location.h gt-stringpool.h : s-gtype ; @true
gtyp-gen.h: Makefile
echo "/* This file is machine generated. Do not edit. */" > tmp-gtyp.h
@@ -2215,7 +2218,7 @@ PREPROCESSOR_DEFINES = \
LIBCPP_OBJS = cpplib.o cpplex.o cppmacro.o cppexp.o cppfiles.o cpptrad.o \
cpphash.o cpperror.o cppinit.o cppdefault.o cppmain.o \
- hashtable.o line-map.o mkdeps.o prefix.o mbchar.o
+ hashtable.o line-map.o mkdeps.o prefix.o mbchar.o cpppch.o
LIBCPP_DEPS = $(CPPLIB_H) cpphash.h line-map.h hashtable.h intl.h \
$(OBSTACK_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H)
@@ -2238,6 +2241,7 @@ cpphash.o: cpphash.c $(LIBCPP_DEPS)
cpptrad.o: cpptrad.c $(LIBCPP_DEPS)
cppfiles.o: cppfiles.c $(LIBCPP_DEPS) $(SPLAY_TREE_H) mkdeps.h
cppinit.o: cppinit.c $(LIBCPP_DEPS) cppdefault.h mkdeps.h prefix.h
+cpppch.o: cpppch.c $(LIBCPP_DEPS) mkdeps.h
cppdefault.o: cppdefault.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) cppdefault.h \
Makefile
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 6b435f5ddd1..0d06e9c725a 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,9 @@
+2003-01-09 Geoffrey Keating <geoffk@apple.com>
+
+ * gnat_rm.texi: Remove RCS version number.
+
+ * ada-tree.h (union lang_tree_node): Add chain_next option.
+
2003-01-09 Christian Cornelssen <ccorn@cs.tu-berlin.de>
* Make-lang.in (ada.install-info, ada.install-common,
diff --git a/gcc/ada/ada-tree.h b/gcc/ada/ada-tree.h
index 53087a7e700..b1904a4284d 100644
--- a/gcc/ada/ada-tree.h
+++ b/gcc/ada/ada-tree.h
@@ -43,7 +43,8 @@ struct tree_loop_id GTY(())
/* The language-specific tree. */
union lang_tree_node
- GTY((desc ("TREE_CODE (&%h.generic) == GNAT_LOOP_ID")))
+ GTY((desc ("TREE_CODE (&%h.generic) == GNAT_LOOP_ID"),
+ chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
{
union tree_node GTY ((tag ("0"),
desc ("tree_node_structure (&%h)")))
diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi
index dd43cf05c65..f9c78ce515e 100644
--- a/gcc/ada/gnat_rm.texi
+++ b/gcc/ada/gnat_rm.texi
@@ -8,8 +8,6 @@
@c o
@c G N A T _ RM o
@c o
-@c $Revision: 1.9 $
-@c o
@c Copyright (C) 1995-2002 Free Software Foundation o
@c o
@c o
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 12cacab3d55..84166c98da3 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -31,6 +31,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "c-pragma.h"
#include "rtl.h"
#include "ggc.h"
+#include "varray.h"
#include "expr.h"
#include "c-common.h"
#include "diagnostic.h"
@@ -190,11 +191,20 @@ enum c_language_kind c_language;
tree c_global_trees[CTI_MAX];
+/* Nonzero if we can read a PCH file now. */
+
+int allow_pch = 1;
+
/* Switches common to the C front ends. */
/* Nonzero if prepreprocessing only. */
int flag_preprocess_only;
+/* The file name to which we should write a precompiled header, or
+ NULL if no header will be written in this compile. */
+
+const char *pch_file;
+
/* Nonzero if an ISO standard was selected. It rejects macros in the
user's namespace. */
int flag_iso;
diff --git a/gcc/c-common.h b/gcc/c-common.h
index 4c60d29fdee..3e976621711 100644
--- a/gcc/c-common.h
+++ b/gcc/c-common.h
@@ -121,7 +121,7 @@ enum rid
/* The elements of `ridpointers' are identifier nodes for the reserved
type names and storage classes. It is indexed by a RID_... value. */
-extern tree *ridpointers;
+extern GTY ((length ("(int)RID_MAX"))) tree *ridpointers;
/* Standard named or nameless data types of the C compiler. */
@@ -177,7 +177,7 @@ enum c_tree_index
struct c_common_identifier GTY(())
{
struct tree_common common;
- struct cpp_hashnode GTY ((skip (""))) node;
+ struct cpp_hashnode node;
};
#define wchar_type_node c_global_trees[CTI_WCHAR_TYPE]
@@ -360,13 +360,24 @@ struct c_lang_decl GTY(()) {
extern c_language_kind c_language;
+/* Nonzero if we can read a PCH file now. */
+
+extern int allow_pch;
+
/* Switches common to the C front ends. */
/* Nonzero if prepreprocessing only. */
+
extern int flag_preprocess_only;
+/* The file name to which we should write a precompiled header, or
+ NULL if no header will be written in this compile. */
+
+extern const char *pch_file;
+
/* Nonzero if an ISO standard was selected. It rejects macros in the
user's namespace. */
+
extern int flag_iso;
/* Nonzero whenever Objective-C functionality is being used. */
@@ -374,6 +385,7 @@ extern int flag_objc;
/* Nonzero if -undef was given. It suppresses target built-in macros
and assertions. */
+
extern int flag_undef;
/* Nonzero means don't recognize the non-ANSI builtin functions. */
@@ -1253,4 +1265,14 @@ extern void dump_time_statistics PARAMS ((void));
extern int c_dump_tree PARAMS ((void *, tree));
+extern void pch_init PARAMS ((void));
+extern int c_common_valid_pch PARAMS ((cpp_reader *pfile,
+ const char *name,
+ int fd));
+extern void c_common_read_pch PARAMS ((cpp_reader *pfile,
+ const char *name,
+ int fd,
+ const char *orig));
+extern void c_common_write_pch PARAMS ((void));
+
#endif /* ! GCC_C_COMMON_H */
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index fde8c482e12..e3d07aab96d 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -3226,6 +3226,8 @@ clear_parm_order ()
current_binding_level->parm_order = NULL_TREE;
}
+static GTY(()) int compound_literal_number;
+
/* Build a COMPOUND_LITERAL_EXPR. TYPE is the type given in the compound
literal, which may be an incomplete array type completed by the
initializer; INIT is a CONSTRUCTOR that initializes the compound
@@ -3273,10 +3275,10 @@ build_compound_literal (type, init)
/* This decl needs a name for the assembler output. We also need
a unique suffix to be added to the name. */
char *name;
- extern int var_labelno;
- ASM_FORMAT_PRIVATE_NAME (name, "__compound_literal", var_labelno);
- var_labelno++;
+ ASM_FORMAT_PRIVATE_NAME (name, "__compound_literal",
+ compound_literal_number);
+ compound_literal_number++;
DECL_NAME (decl) = get_identifier (name);
DECL_DEFER_OUTPUT (decl) = 1;
DECL_COMDAT (decl) = 1;
diff --git a/gcc/c-lex.c b/gcc/c-lex.c
index 5507e6311d0..a689ccab004 100644
--- a/gcc/c-lex.c
+++ b/gcc/c-lex.c
@@ -124,6 +124,8 @@ init_c_lex (filename)
cb->ident = cb_ident;
cb->file_change = cb_file_change;
cb->def_pragma = cb_def_pragma;
+ cb->valid_pch = c_common_valid_pch;
+ cb->read_pch = c_common_read_pch;
/* Set the debug callbacks if we can use them. */
if (debug_info_level == DINFO_LEVEL_VERBOSE
@@ -158,6 +160,8 @@ c_common_parse_file (set_yydebug)
(*debug_hooks->start_source_file) (lineno, input_filename);
cpp_finish_options (parse_in);
+ pch_init();
+
yyparse ();
free_parser_stacks ();
}
diff --git a/gcc/c-objc-common.c b/gcc/c-objc-common.c
index 7d54d7ace4d..c91e635b410 100644
--- a/gcc/c-objc-common.c
+++ b/gcc/c-objc-common.c
@@ -1,5 +1,5 @@
/* Some code common to C and ObjC front ends.
- Copyright (C) 2001 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
@@ -358,6 +358,9 @@ finish_cdtor (body)
void
c_objc_common_finish_file ()
{
+ if (pch_file)
+ c_common_write_pch ();
+
expand_deferred_fns ();
if (static_ctors)
diff --git a/gcc/c-opts.c b/gcc/c-opts.c
index 85ed5f325aa..5270d625a20 100644
--- a/gcc/c-opts.c
+++ b/gcc/c-opts.c
@@ -112,6 +112,7 @@ static void sanitize_cpp_opts PARAMS ((void));
#define COMMAND_LINE_OPTIONS \
OPT("-help", CL_ALL, OPT__help) \
+ OPT("-output-pch=", CL_ALL | CL_ARG, OPT__output_pch) \
OPT("C", CL_ALL, OPT_C) \
OPT("CC", CL_ALL, OPT_CC) \
OPT("E", CL_ALL, OPT_E) \
@@ -154,6 +155,7 @@ static void sanitize_cpp_opts PARAMS ((void));
OPT("Wimplicit-function-declaration", CL_C, OPT_Wimplicit_function_decl) \
OPT("Wimplicit-int", CL_C, OPT_Wimplicit_int) \
OPT("Wimport", CL_ALL, OPT_Wimport) \
+ OPT("Winvalid-pch", CL_ALL, OPT_Winvalid_pch) \
OPT("Wlong-long", CL_ALL, OPT_Wlong_long) \
OPT("Wmain", CL_C, OPT_Wmain) \
OPT("Wmissing-braces", CL_ALL, OPT_Wmissing_braces) \
@@ -231,6 +233,7 @@ static void sanitize_cpp_opts PARAMS ((void));
OPT("fnonnull-objects", CL_CXX, OPT_fnonnull_objects) \
OPT("foperator-names", CL_CXX, OPT_foperator_names) \
OPT("foptional-diags", CL_CXX, OPT_foptional_diags) \
+ OPT("fpch-deps", CL_ALL, OPT_fpch_deps) \
OPT("fpermissive", CL_CXX, OPT_fpermissive) \
OPT("fpreprocessed", CL_ALL, OPT_fpreprocessed) \
OPT("frepo", CL_CXX, OPT_frepo) \
@@ -343,6 +346,7 @@ missing_arg (opt_index)
switch (cl_options[opt_index].opt_code)
{
+ case OPT__output_pch:
case OPT_Wformat_eq:
case OPT_d:
case OPT_fabi_version:
@@ -627,6 +631,10 @@ c_common_decode_option (argc, argv)
print_help ();
break;
+ case OPT__output_pch:
+ pch_file = arg;
+ break;
+
case OPT_C:
cpp_opts->discard_comments = 0;
break;
@@ -832,6 +840,10 @@ c_common_decode_option (argc, argv)
cpp_opts->warn_import = on;
break;
+ case OPT_Winvalid_pch:
+ cpp_opts->warn_invalid_pch = on;
+ break;
+
case OPT_Wlong_long:
warn_long_long = on;
break;
@@ -1178,6 +1190,10 @@ c_common_decode_option (argc, argv)
flag_optional_diags = on;
break;
+ case OPT_fpch_deps:
+ cpp_opts->restore_pch_deps = on;
+ break;
+
case OPT_fpermissive:
flag_permissive = on;
break;
diff --git a/gcc/c-parse.in b/gcc/c-parse.in
index 70dfe905dfc..72ca4fe287b 100644
--- a/gcc/c-parse.in
+++ b/gcc/c-parse.in
@@ -48,6 +48,7 @@ end ifc
#include "c-pragma.h" /* For YYDEBUG definition, and parse_in. */
#include "c-tree.h"
#include "flags.h"
+#include "varray.h"
#include "output.h"
#include "toplev.h"
#include "ggc.h"
@@ -3555,10 +3556,7 @@ init_reswords ()
if (!flag_objc)
mask |= D_OBJC;
- /* It is not necessary to register ridpointers as a GC root, because
- all the trees it points to are permanently interned in the
- get_identifier hash anyway. */
- ridpointers = (tree *) xcalloc ((int) RID_MAX, sizeof (tree));
+ ridpointers = (tree *) ggc_calloc ((int) RID_MAX, sizeof (tree));
for (i = 0; i < N_reswords; i++)
{
/* If a keyword is disabled, do not enter it into the table
diff --git a/gcc/c-pch.c b/gcc/c-pch.c
new file mode 100644
index 00000000000..616e002a828
--- /dev/null
+++ b/gcc/c-pch.c
@@ -0,0 +1,226 @@
+/* Precompiled header implementation for the C languages.
+ Copyright (C) 2000, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "cpplib.h"
+#include "tree.h"
+#include "c-common.h"
+#include "output.h"
+#include "toplev.h"
+#include "debug.h"
+#include "c-pragma.h"
+#include "ggc.h"
+
+struct c_pch_header
+{
+ unsigned long asm_size;
+};
+
+static const char pch_ident[8] = "gpchC010";
+
+static FILE *pch_outfile;
+
+extern char *asm_file_name;
+static off_t asm_file_startpos;
+
+void
+pch_init ()
+{
+ FILE *f;
+
+ if (pch_file)
+ {
+ /* We're precompiling a header file, so when it's actually used,
+ it'll be at least one level deep. */
+ (*debug_hooks->start_source_file) (lineno, input_filename);
+
+ f = fopen (pch_file, "w+b");
+ if (f == NULL)
+ fatal_io_error ("can't open %s", pch_file);
+ pch_outfile = f;
+
+ if (fwrite (pch_ident, sizeof (pch_ident), 1, f) != 1)
+ fatal_io_error ("can't write to %s", pch_file);
+
+ /* We need to be able to re-read the output. */
+ /* The driver always provides a valid -o option. */
+ if (asm_file_name == NULL
+ || strcmp (asm_file_name, "-") == 0)
+ fatal_error ("`%s' is not a valid output file", asm_file_name);
+
+ asm_file_startpos = ftello (asm_out_file);
+
+ cpp_save_state (parse_in, f);
+ }
+}
+
+void
+c_common_write_pch ()
+{
+ char *buf;
+ off_t asm_file_end;
+ off_t written;
+ struct c_pch_header h;
+
+ cpp_write_pch_deps (parse_in, pch_outfile);
+
+ asm_file_end = ftello (asm_out_file);
+ h.asm_size = asm_file_end - asm_file_startpos;
+
+ if (fwrite (&h, sizeof (h), 1, pch_outfile) != 1)
+ fatal_io_error ("can't write %s", pch_file);
+
+ buf = xmalloc (16384);
+ fflush (asm_out_file);
+
+ if (fseeko (asm_out_file, asm_file_startpos, SEEK_SET) != 0)
+ fatal_io_error ("can't seek in %s", asm_file_name);
+
+ for (written = asm_file_startpos; written < asm_file_end; )
+ {
+ off_t size = asm_file_end - written;
+ if (size > 16384)
+ size = 16384;
+ if (fread (buf, size, 1, asm_out_file) != 1)
+ fatal_io_error ("can't read %s", asm_file_name);
+ if (fwrite (buf, size, 1, pch_outfile) != 1)
+ fatal_io_error ("can't write %s", pch_file);
+ written += size;
+ }
+ free (buf);
+
+ gt_pch_save (pch_outfile);
+ cpp_write_pch_state (parse_in, pch_outfile);
+
+ fclose (pch_outfile);
+}
+
+int
+c_common_valid_pch (pfile, name, fd)
+ cpp_reader *pfile;
+ const char *name;
+ int fd;
+{
+ int sizeread;
+ int result;
+ char ident[sizeof (pch_ident)];
+
+ if (! allow_pch)
+ return 2;
+
+ /* Perform a quick test of whether this is a valid
+ precompiled header for C. */
+
+ sizeread = read (fd, ident, sizeof (pch_ident));
+ if (sizeread == -1)
+ {
+ fatal_io_error ("can't read %s", name);
+ return 2;
+ }
+ else if (sizeread != sizeof (pch_ident))
+ return 2;
+
+ if (memcmp (ident, pch_ident, sizeof (pch_ident)) != 0)
+ {
+ if (cpp_get_options (pfile)->warn_invalid_pch)
+ {
+ if (memcmp (ident, pch_ident, 5) == 0)
+ /* It's a PCH, for the right language, but has the wrong version.
+ */
+ cpp_error (pfile, DL_WARNING,
+ "%s: not compatible with this GCC version", name);
+ else if (memcmp (ident, pch_ident, 4) == 0)
+ /* It's a PCH for the wrong language. */
+ cpp_error (pfile, DL_WARNING, "%s: not for C language", name);
+ else
+ /* Not any kind of PCH. */
+ cpp_error (pfile, DL_WARNING, "%s: not a PCH file", name);
+ }
+ return 2;
+ }
+
+ /* Check the preprocessor macros are the same as when the PCH was
+ generated. */
+
+ result = cpp_valid_state (pfile, name, fd);
+ if (result == -1)
+ return 2;
+ else
+ return result == 0;
+}
+
+void
+c_common_read_pch (pfile, name, fd, orig_name)
+ cpp_reader *pfile;
+ const char *name;
+ int fd;
+ const char *orig_name;
+{
+ FILE *f;
+ struct c_pch_header h;
+ char *buf;
+ unsigned long written;
+ struct save_macro_data *smd;
+
+ /* Before we wrote the file, we started a source file, so we have to start
+ one here to match. */
+ (*debug_hooks->start_source_file) (lineno, orig_name);
+
+ f = fdopen (fd, "rb");
+ if (f == NULL)
+ {
+ cpp_errno (pfile, DL_ERROR, "calling fdopen");
+ return;
+ }
+
+ allow_pch = 0;
+
+ if (fread (&h, sizeof (h), 1, f) != 1)
+ {
+ cpp_errno (pfile, DL_ERROR, "reading");
+ return;
+ }
+
+ buf = xmalloc (16384);
+ for (written = 0; written < h.asm_size; )
+ {
+ off_t size = h.asm_size - written;
+ if (size > 16384)
+ size = 16384;
+ if (fread (buf, size, 1, f) != 1
+ || fwrite (buf, size, 1, asm_out_file) != 1)
+ cpp_errno (pfile, DL_ERROR, "reading");
+ written += size;
+ }
+ free (buf);
+
+ cpp_prepare_state (pfile, &smd);
+
+ gt_pch_restore (f);
+
+ if (cpp_read_state (pfile, name, f, smd) != 0)
+ return;
+
+ fclose (f);
+
+ (*debug_hooks->end_source_file) (lineno);
+}
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index ce0810d0d26..dbbf1103dea 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -50,6 +50,7 @@ Boston, MA 02111-1307, USA. */
#include "target-def.h"
#include "debug.h"
#include "langhooks.h"
+#include <splay-tree.h>
/* Specify which cpu to schedule for. */
@@ -9023,6 +9024,20 @@ alpha_elf_select_rtx_section (mode, x, align)
#endif /* OBJECT_FORMAT_ELF */
+/* Structure to collect function names for final output
+ in link section. */
+
+enum links_kind {KIND_UNUSED, KIND_LOCAL, KIND_EXTERN};
+
+struct alpha_links GTY(())
+{
+ rtx linkage;
+ enum links_kind kind;
+};
+
+static GTY ((param1_is (char *), param2_is (struct alpha_links *)))
+ splay_tree alpha_links;
+
#if TARGET_ABI_OPEN_VMS
/* Return the VMS argument type corresponding to MODE. */
@@ -9058,26 +9073,6 @@ alpha_arg_info_reg_val (cum)
return GEN_INT (regval);
}
-/* Protect alpha_links from garbage collection. */
-
-static int
-mark_alpha_links_node (node, data)
- splay_tree_node node;
- void *data ATTRIBUTE_UNUSED;
-{
- struct alpha_links *links = (struct alpha_links *) node->value;
- ggc_mark_rtx (links->linkage);
- return 0;
-}
-
-static void
-mark_alpha_links (ptr)
- void *ptr;
-{
- splay_tree tree = *(splay_tree *) ptr;
- splay_tree_foreach (tree, mark_alpha_links_node, NULL);
-}
-
/* Make (or fake) .linkage entry for function call.
IS_LOCAL is 0 if name is used in call, 1 if name is used in definition.
@@ -9139,16 +9134,11 @@ alpha_need_linkage (name, is_local)
}
else
{
- alpha_links_tree = splay_tree_new
- ((splay_tree_compare_fn) strcmp,
- (splay_tree_delete_key_fn) free,
- (splay_tree_delete_key_fn) free);
-
- ggc_add_root (&alpha_links_tree, 1, 1, mark_alpha_links);
+ alpha_links = splay_tree_new_ggc ((splay_tree_compare_fn) strcmp);
}
- al = (struct alpha_links *) xmalloc (sizeof (struct alpha_links));
- name = xstrdup (name);
+ al = (struct alpha_links *) ggc_alloc (sizeof (struct alpha_links));
+ name = ggc_strdup (name);
/* Assume external if no definition. */
al->lkind = (is_local ? KIND_UNUSED : KIND_EXTERN);
diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c
index a7dfe59bec6..bce6d11e132 100644
--- a/gcc/config/darwin.c
+++ b/gcc/config/darwin.c
@@ -223,7 +223,7 @@ machopic_define_name (name)
static char function_base[32];
-static int current_pic_label_num;
+static GTY(()) int current_pic_label_num;
const char *
machopic_function_base_name ()
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 6112737d5b1..7880cd5c9f8 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -168,7 +168,6 @@ struct builtin_description
};
static bool rs6000_function_ok_for_sibcall PARAMS ((tree, tree));
-static void rs6000_add_gc_roots PARAMS ((void));
static int num_insns_constant_wide PARAMS ((HOST_WIDE_INT));
static void validate_condition_mode
PARAMS ((enum rtx_code, enum machine_mode));
@@ -183,8 +182,6 @@ static void rs6000_emit_allocate_stack PARAMS ((HOST_WIDE_INT, int));
static unsigned rs6000_hash_constant PARAMS ((rtx));
static unsigned toc_hash_function PARAMS ((const void *));
static int toc_hash_eq PARAMS ((const void *, const void *));
-static int toc_hash_mark_entry PARAMS ((void **, void *));
-static void toc_hash_mark_table PARAMS ((void *));
static int constant_pool_expr_1 PARAMS ((rtx, int *, int *));
static struct machine_function * rs6000_init_machine_status PARAMS ((void));
static bool rs6000_assemble_integer PARAMS ((rtx, unsigned int, int));
@@ -267,6 +264,19 @@ static void is_altivec_return_reg PARAMS ((rtx, void *));
static rtx generate_set_vrsave PARAMS ((rtx, rs6000_stack_t *, int));
static void altivec_frame_fixup PARAMS ((rtx, rtx, HOST_WIDE_INT));
static int easy_vector_constant PARAMS ((rtx));
+
+/* Hash table stuff for keeping track of TOC entries. */
+
+struct toc_hash_struct GTY(())
+{
+ /* `key' will satisfy CONSTANT_P; in fact, it will satisfy
+ ASM_OUTPUT_SPECIAL_POOL_ENTRY_P. */
+ rtx key;
+ enum machine_mode key_mode;
+ int labelno;
+};
+
+static GTY ((param_is (struct toc_hash_struct))) htab_t toc_hash_table;
/* Default register names. */
char rs6000_reg_names[][8] =
@@ -708,9 +718,6 @@ rs6000_override_options (default_cpu)
&& (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN))
real_format_for_mode[TFmode - QFmode] = &ibm_extended_format;
- /* Register global variables with the garbage collector. */
- rs6000_add_gc_roots ();
-
/* Allocate an alias set for register saves & restores from stack. */
rs6000_sr_alias_set = new_alias_set ();
@@ -11457,19 +11464,6 @@ rs6000_output_mi_thunk (file, thunk_fndecl, delta, vcall_offset, function)
*/
-/* Hash table stuff for keeping track of TOC entries. */
-
-struct toc_hash_struct
-{
- /* `key' will satisfy CONSTANT_P; in fact, it will satisfy
- ASM_OUTPUT_SPECIAL_POOL_ENTRY_P. */
- rtx key;
- enum machine_mode key_mode;
- int labelno;
-};
-
-static htab_t toc_hash_table;
-
/* Hash functions for the hash table. */
static unsigned
@@ -11570,39 +11564,6 @@ toc_hash_eq (h1, h2)
return rtx_equal_p (r1, r2);
}
-/* Mark the hash table-entry HASH_ENTRY. */
-
-static int
-toc_hash_mark_entry (hash_slot, unused)
- void ** hash_slot;
- void * unused ATTRIBUTE_UNUSED;
-{
- const struct toc_hash_struct * hash_entry =
- *(const struct toc_hash_struct **) hash_slot;
- rtx r = hash_entry->key;
- ggc_set_mark (hash_entry);
- /* For CODE_LABELS, we don't want to drag in the whole insn chain... */
- if (GET_CODE (r) == LABEL_REF)
- {
- ggc_set_mark (r);
- ggc_set_mark (XEXP (r, 0));
- }
- else
- ggc_mark_rtx (r);
- return 1;
-}
-
-/* Mark all the elements of the TOC hash-table *HT. */
-
-static void
-toc_hash_mark_table (vht)
- void *vht;
-{
- htab_t *ht = vht;
-
- htab_traverse (*ht, toc_hash_mark_entry, (void *)0);
-}
-
/* These are the names given by the C++ front-end to vtables, and
vtable-like objects. Ideally, this logic should not be here;
instead, there should be some programmatic way of inquiring as
@@ -11656,12 +11617,19 @@ output_toc (file, x, labelno, mode)
/* When the linker won't eliminate them, don't output duplicate
TOC entries (this happens on AIX if there is any kind of TOC,
- and on SVR4 under -fPIC or -mrelocatable). */
- if (TARGET_TOC)
+ and on SVR4 under -fPIC or -mrelocatable). Don't do this for
+ CODE_LABELs. */
+ if (TARGET_TOC && GET_CODE (x) != LABEL_REF)
{
struct toc_hash_struct *h;
void * * found;
+ /* Create toc_hash_table. This can't be done at OVERRIDE_OPTIONS
+ time because GGC is not initialised at that point. */
+ if (toc_hash_table == NULL)
+ toc_hash_table = htab_create_ggc (1021, toc_hash_function,
+ toc_hash_eq, NULL);
+
h = ggc_alloc (sizeof (*h));
h->key = x;
h->key_mode = mode;
@@ -12685,17 +12653,6 @@ rs6000_fatal_bad_address (op)
fatal_insn ("bad address", op);
}
-/* Called to register all of our global variables with the garbage
- collector. */
-
-static void
-rs6000_add_gc_roots ()
-{
- toc_hash_table = htab_create (1021, toc_hash_function, toc_hash_eq, NULL);
- ggc_add_root (&toc_hash_table, 1, sizeof (toc_hash_table),
- toc_hash_mark_table);
-}
-
#if TARGET_MACHO
#if 0
@@ -13312,3 +13269,4 @@ rs6000_memory_move_cost (mode, class, in)
return 4 + rs6000_register_move_cost (mode, class, GENERAL_REGS);
}
+#include "gt-rs6000.h"
diff --git a/gcc/config/rs6000/t-rs6000 b/gcc/config/rs6000/t-rs6000
index 805e15d4e82..c2a7848711b 100644
--- a/gcc/config/rs6000/t-rs6000
+++ b/gcc/config/rs6000/t-rs6000
@@ -1,14 +1,17 @@
# General rules that all rs6000/ targets must have.
+gt-rs6000.h: s-gtype ; @true
+
rs6000.o: $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(RTL_H) $(REGS_H) hard-reg-set.h \
real.h insn-config.h conditions.h insn-attr.h flags.h $(RECOG_H) \
$(OBSTACK_H) $(TREE_H) $(EXPR_H) $(OPTABS_H) except.h function.h \
output.h $(BASIC_BLOCK_H) $(INTEGRATE_H) toplev.h $(GGC_H) $(HASHTAB_H) \
- $(TM_P_H) $(TARGET_H) $(TARGET_DEF_H) langhooks.h reload.h
+ $(TM_P_H) $(TARGET_H) $(TARGET_DEF_H) langhooks.h reload.h gt-rs6000.h
rs6000-c.o: $(srcdir)/config/rs6000/rs6000-c.c \
$(srcdir)/config/rs6000/rs6000-protos.h \
$(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(CPPLIB_H) \
$(TM_P_H) c-pragma.h errors.h coretypes.h $(TM_H)
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/rs6000/rs6000-c.c
+
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 2970abba965..fb530434027 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,93 @@
+2003-01-09 Geoffrey Keating <geoffk@apple.com>
+
+ Merge from pch-branch:
+
+ 2003-01-09 Geoffrey Keating <geoffk@apple.com>
+
+ Merge to tag pch-merge-20030102:
+
+ * semantics.c (finish_translation_unit): Don't call finish_file.
+ * parser.c: Don't include ggc.h.
+ (cp_lexer_new_main): Rename from cp_lexer_new, only create main lexer,
+ read first token here. Don't allow PCH files after the first
+ token is read.
+ (cp_lexer_new_from_tokens): Duplicate functionality from cp_lexer_new.
+ (cp_lexer_get_preprocessor_token): Allow LEXER to be NULL.
+ (cp_parser_new): Call cp_lexer_new_main before allocating GCed memory.
+ (cp_parser_late_parsing_for_member): Don't duplicate call to
+ cp_lexer_set_source_position_from_token.
+ (cp_parser_late_parsing_default_args): Likewise.
+ (yyparse): Call finish_file after clearing the_parser.
+
+ 2002-12-11 Geoffrey Keating <geoffk@apple.com>
+
+ * Make-lang.in: Remove $(GGC_H) from all dependencies.
+ (CXX_TREE_H): Add $(GGC_H).
+ * class.c: Don't include ggc.h.
+ (field_decl_cmp): Make parameters be 'const void *' to match qsort.
+ (method_name_cmp): Likewise.
+ (resort_data): New variable.
+ (resort_field_decl_cmp): New.
+ (resort_method_name_cmp): New.
+ (resort_sorted_fields): New.
+ (resort_type_method_vec): New.
+ (finish_struct_methods): Delete cast.
+ (finish_struct_1): Delete cast.
+ * cp-tree.h: Include ggc.h.
+ (struct lang_type_class): Add reorder attribute to field `methods'.
+ (union lang_decl_u3): Add reorder attribute to field `sorted_fields'.
+ (resort_sorted_fields): New prototype.
+ (resort_type_method_vec): New prototype.
+ * call.c: Don't include ggc.h.
+ * decl.c: Likewise.
+ * decl2.c: Likewise.
+ * init.c: Likewise.
+ * lex.c: Likewise.
+ * method.c: Likewise.
+ * optimize.c: Likewise.
+ * parse.y: Likewise.
+ * pt.c: Likewise.
+ * repo.c: Likewise.
+ * search.c: Likewise.
+ * semantics.c: Likewise.
+ * spew.c: Likewise.
+ * tree.c: Likewise.
+
+ * lang-specs.h: Remove comment.
+
+ 2002-12-03 Geoffrey Keating <geoffk@apple.com>
+
+ * cp-tree.h (struct operator_name_info_t): Mark for GTY machinery.
+ (operator_name_info): Mark to be saved for PCH, specify size.
+ (assignment_operator_name_info): Likewise.
+
+ 2002-11-19 Geoffrey Keating <geoffk@apple.com>
+
+ * decl.c (anon_cnt): Mark to be saved for PCH.
+
+ 2002-10-25 Geoffrey Keating <geoffk@apple.com>
+
+ * lex.c (init_reswords): Delete now-untrue comment.
+ Allocate ridpointers using GGC.
+
+ 2002-10-04 Geoffrey Keating <geoffk@apple.com>
+
+ * cp-tree.h (union lang_decl_u2): Add tags to all fields.
+
+ * g++spec.c (lang_specific_driver): Don't include standard
+ libraries in `added'.
+
+ 2002-08-27 Geoffrey Keating <geoffk@redhat.com>
+
+ * decl2.c (finish_file): Call c_common_write_pch.
+ * Make-lang.in (CXX_C_OBJS): Add c-pch.o.
+
+ 2002-08-17 Geoffrey Keating <geoffk@redhat.com>
+
+ * g++spec.c (lang_specific_driver): Treat .h files as C++ header
+ files when using g++.
+ * lang-specs.h: Handle compiling C++ header files.
+
2003-01-09 Jakub Jelinek <jakub@redhat.com>
* decl.c (start_decl): Only check DECL_THREAD_LOCAL for VAR_DECLs.
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index b54e3ba678f..347b71a906a 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -1,5 +1,5 @@
# Top level -*- makefile -*- fragment for GNU C++.
-# Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002
+# Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003
# Free Software Foundation, Inc.
#This file is part of GCC.
@@ -79,7 +79,7 @@ g++-cross$(exeext): g++$(exeext)
# The compiler itself.
# Shared with C front end:
CXX_C_OBJS = attribs.o c-common.o c-format.o c-pragma.o c-semantics.o c-lex.o \
- c-dump.o $(CXX_TARGET_OBJS) c-pretty-print.o c-opts.o
+ c-dump.o $(CXX_TARGET_OBJS) c-pretty-print.o c-opts.o c-pch.o
# Language-specific object files.
CXX_OBJS = cp/call.o cp/decl.o cp/expr.o cp/pt.o cp/typeck2.o \
@@ -210,34 +210,35 @@ c++.stage4: stage4-start
# .o: .h dependencies.
CXX_TREE_H = $(TREE_H) cp/cp-tree.h c-common.h cp/cp-tree.def c-common.def \
function.h varray.h $(SYSTEM_H) coretypes.h $(CONFIG_H) $(TARGET_H) \
+ $(GGC_H) \
$(srcdir)/../include/hashtab.h $(srcdir)/../include/splay-tree.h
cp/lex.o: cp/lex.c $(CXX_TREE_H) $(TM_H) flags.h cp/lex.h \
- c-pragma.h toplev.h output.h mbchar.h $(GGC_H) input.h diagnostic.h \
+ c-pragma.h toplev.h output.h mbchar.h input.h diagnostic.h \
cp/operators.def $(TM_P_H)
cp/cp-lang.o: cp/cp-lang.c $(CXX_TREE_H) $(TM_H) toplev.h langhooks.h \
$(LANGHOOKS_DEF_H) c-common.h
cp/decl.o: cp/decl.c $(CXX_TREE_H) $(TM_H) flags.h cp/lex.h cp/decl.h stack.h \
- output.h $(EXPR_H) except.h toplev.h $(HASHTAB_H) $(GGC_H) $(RTL_H) \
+ output.h $(EXPR_H) except.h toplev.h $(HASHTAB_H) $(RTL_H) \
cp/operators.def $(TM_P_H) tree-inline.h diagnostic.h c-pragma.h \
debug.h gt-cp-decl.h gtype-cp.h
cp/decl2.o: cp/decl2.c $(CXX_TREE_H) $(TM_H) flags.h cp/lex.h cp/decl.h $(EXPR_H) \
- output.h except.h toplev.h $(GGC_H) $(RTL_H) c-common.h gt-cp-decl2.h
+ output.h except.h toplev.h $(RTL_H) c-common.h gt-cp-decl2.h
cp/typeck2.o: cp/typeck2.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h output.h $(TM_P_H) \
diagnostic.h
cp/typeck.o: cp/typeck.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) $(EXPR_H) toplev.h \
diagnostic.h
cp/class.o: cp/class.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_H) $(TARGET_H)
cp/call.o: cp/call.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_H) $(EXPR_H) \
- $(GGC_H) diagnostic.h gt-cp-call.h
+ diagnostic.h gt-cp-call.h
cp/friend.o: cp/friend.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) toplev.h $(EXPR_H)
cp/init.o: cp/init.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) $(EXPR_H) toplev.h \
- $(GGC_H) except.h
-cp/method.o: cp/method.c $(CXX_TREE_H) $(TM_H) toplev.h $(GGC_H) $(RTL_H) $(EXPR_H) \
+ except.h
+cp/method.o: cp/method.c $(CXX_TREE_H) $(TM_H) toplev.h $(RTL_H) $(EXPR_H) \
$(TM_P_H) $(TARGET_H)
cp/cvt.o: cp/cvt.c $(CXX_TREE_H) $(TM_H) cp/decl.h flags.h toplev.h convert.h
cp/search.o: cp/search.c $(CXX_TREE_H) $(TM_H) stack.h flags.h toplev.h $(RTL_H)
-cp/tree.o: cp/tree.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(GGC_H) $(RTL_H) \
+cp/tree.o: cp/tree.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_H) \
insn-config.h integrate.h tree-inline.h real.h gt-cp-tree.h $(TARGET_H)
cp/ptree.o: cp/ptree.c $(CXX_TREE_H) $(TM_H)
cp/rtti.o: cp/rtti.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h
@@ -246,13 +247,13 @@ cp/except.o: cp/except.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) except.h toplev.
cp/expr.o: cp/expr.c $(CXX_TREE_H) $(TM_H) $(RTL_H) flags.h $(EXPR_H) toplev.h \
except.h $(TM_P_H)
cp/pt.o: cp/pt.c $(CXX_TREE_H) $(TM_H) cp/decl.h cp/lex.h \
- toplev.h $(GGC_H) $(RTL_H) except.h tree-inline.h gt-cp-pt.h
+ toplev.h $(RTL_H) except.h tree-inline.h gt-cp-pt.h
cp/error.o: cp/error.c $(CXX_TREE_H) $(TM_H) toplev.h diagnostic.h flags.h real.h \
$(LANGHOOKS_DEF_H)
-cp/repo.o: cp/repo.c $(CXX_TREE_H) $(TM_H) toplev.h $(GGC_H) diagnostic.h \
+cp/repo.o: cp/repo.c $(CXX_TREE_H) $(TM_H) toplev.h diagnostic.h \
gt-cp-repo.h
cp/semantics.o: cp/semantics.c $(CXX_TREE_H) $(TM_H) cp/lex.h except.h toplev.h \
- flags.h $(GGC_H) debug.h output.h $(RTL_H) $(TIMEVAR_H) $(EXPR_H) \
+ flags.h debug.h output.h $(RTL_H) $(TIMEVAR_H) $(EXPR_H) \
tree-inline.h
cp/dump.o: cp/dump.c $(CXX_TREE_H) $(TM_H) tree-dump.h
cp/optimize.o: cp/optimize.c $(CXX_TREE_H) $(TM_H) rtl.h integrate.h insn-config.h \
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 00458c06248..cd93f7bbe4b 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -35,7 +35,6 @@ Boston, MA 02111-1307, USA. */
#include "rtl.h"
#include "toplev.h"
#include "expr.h"
-#include "ggc.h"
#include "diagnostic.h"
extern int inhibit_warnings;
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 845ca19c738..bace3f4d7c9 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -33,7 +33,6 @@ Boston, MA 02111-1307, USA. */
#include "rtl.h"
#include "output.h"
#include "toplev.h"
-#include "ggc.h"
#include "lex.h"
#include "target.h"
@@ -125,8 +124,10 @@ static tree modify_all_vtables PARAMS ((tree, tree));
static void determine_primary_base PARAMS ((tree));
static void finish_struct_methods PARAMS ((tree));
static void maybe_warn_about_overly_private_class PARAMS ((tree));
-static int field_decl_cmp PARAMS ((const tree *, const tree *));
-static int method_name_cmp PARAMS ((const tree *, const tree *));
+static int field_decl_cmp PARAMS ((const void *, const void *));
+static int resort_field_decl_cmp PARAMS ((const void *, const void *));
+static int method_name_cmp PARAMS ((const void *, const void *));
+static int resort_method_name_cmp PARAMS ((const void *, const void *));
static void add_implicitly_declared_members PARAMS ((tree, int, int, int));
static tree fixed_type_or_null PARAMS ((tree, int *, int *));
static tree resolve_address_of_overloaded_function PARAMS ((tree, tree, int,
@@ -1449,7 +1450,8 @@ mark_primary_virtual_base (base_binfo, type)
base, then BINFO has no primary base in this graph. Called from
mark_primary_bases. DATA is the most derived type. */
-static tree dfs_unshared_virtual_bases (binfo, data)
+static tree
+dfs_unshared_virtual_bases (binfo, data)
tree binfo;
void *data;
{
@@ -1923,9 +1925,11 @@ maybe_warn_about_overly_private_class (t)
/* Function to help qsort sort FIELD_DECLs by name order. */
static int
-field_decl_cmp (x, y)
- const tree *x, *y;
+field_decl_cmp (x_p, y_p)
+ const void *x_p, *y_p;
{
+ const tree *const x = x_p;
+ const tree *const y = y_p;
if (DECL_NAME (*x) == DECL_NAME (*y))
/* A nontype is "greater" than a type. */
return DECL_DECLARES_TYPE_P (*y) - DECL_DECLARES_TYPE_P (*x);
@@ -1938,12 +1942,64 @@ field_decl_cmp (x, y)
return 1;
}
+static struct {
+ gt_pointer_operator new_value;
+ void *cookie;
+} resort_data;
+
+/* This routine compares two fields like field_decl_cmp but using the
+ pointer operator in resort_data. */
+
+static int
+resort_field_decl_cmp (x_p, y_p)
+ const void *x_p, *y_p;
+{
+ const tree *const x = x_p;
+ const tree *const y = y_p;
+
+ if (DECL_NAME (*x) == DECL_NAME (*y))
+ /* A nontype is "greater" than a type. */
+ return DECL_DECLARES_TYPE_P (*y) - DECL_DECLARES_TYPE_P (*x);
+ if (DECL_NAME (*x) == NULL_TREE)
+ return -1;
+ if (DECL_NAME (*y) == NULL_TREE)
+ return 1;
+ {
+ tree d1 = DECL_NAME (*x);
+ tree d2 = DECL_NAME (*y);
+ resort_data.new_value (&d1, resort_data.cookie);
+ resort_data.new_value (&d2, resort_data.cookie);
+ if (d1 < d2)
+ return -1;
+ }
+ return 1;
+}
+
+/* Resort DECL_SORTED_FIELDS because pointers have been reordered. */
+
+void
+resort_sorted_fields (obj, orig_obj, new_value, cookie)
+ void *obj;
+ void *orig_obj;
+ gt_pointer_operator new_value;
+ void *cookie;
+{
+ tree sf = obj;
+ resort_data.new_value = new_value;
+ resort_data.cookie = cookie;
+ qsort (&TREE_VEC_ELT (sf, 0), TREE_VEC_LENGTH (sf), sizeof (tree),
+ resort_field_decl_cmp);
+}
+
/* Comparison function to compare two TYPE_METHOD_VEC entries by name. */
static int
-method_name_cmp (m1, m2)
- const tree *m1, *m2;
+method_name_cmp (m1_p, m2_p)
+ const void *m1_p, *m2_p;
{
+ const tree *const m1 = m1_p;
+ const tree *const m2 = m2_p;
+
if (*m1 == NULL_TREE && *m2 == NULL_TREE)
return 0;
if (*m1 == NULL_TREE)
@@ -1955,6 +2011,63 @@ method_name_cmp (m1, m2)
return 1;
}
+/* This routine compares two fields like method_name_cmp but using the
+ pointer operator in resort_field_decl_data. */
+
+static int
+resort_method_name_cmp (m1_p, m2_p)
+ const void *m1_p, *m2_p;
+{
+ const tree *const m1 = m1_p;
+ const tree *const m2 = m2_p;
+ if (*m1 == NULL_TREE && *m2 == NULL_TREE)
+ return 0;
+ if (*m1 == NULL_TREE)
+ return -1;
+ if (*m2 == NULL_TREE)
+ return 1;
+ {
+ tree d1 = DECL_NAME (OVL_CURRENT (*m1));
+ tree d2 = DECL_NAME (OVL_CURRENT (*m2));
+ resort_data.new_value (&d1, resort_data.cookie);
+ resort_data.new_value (&d2, resort_data.cookie);
+ if (d1 < d2)
+ return -1;
+ }
+ return 1;
+}
+
+/* Resort TYPE_METHOD_VEC because pointers have been reordered. */
+
+void
+resort_type_method_vec (obj, orig_obj, new_value, cookie)
+ void *obj;
+ void *orig_obj;
+ gt_pointer_operator new_value;
+ void *cookie;
+{
+ tree method_vec = obj;
+ int len = TREE_VEC_LENGTH (method_vec);
+ int slot;
+
+ /* The type conversion ops have to live at the front of the vec, so we
+ can't sort them. */
+ for (slot = 2; slot < len; ++slot)
+ {
+ tree fn = TREE_VEC_ELT (method_vec, slot);
+
+ if (!DECL_CONV_FN_P (OVL_CURRENT (fn)))
+ break;
+ }
+ if (len - slot > 1)
+ {
+ resort_data.new_value = new_value;
+ resort_data.cookie = cookie;
+ qsort (&TREE_VEC_ELT (method_vec, slot), len - slot, sizeof (tree),
+ resort_method_name_cmp);
+ }
+}
+
/* Warn about duplicate methods in fn_fields. Also compact method
lists so that lookup can be made faster.
@@ -2025,7 +2138,7 @@ finish_struct_methods (t)
}
if (len - slot > 1)
qsort (&TREE_VEC_ELT (method_vec, slot), len-slot, sizeof (tree),
- (int (*)(const void *, const void *))method_name_cmp);
+ method_name_cmp);
}
/* Emit error when a duplicate definition of a type is seen. Patch up. */
@@ -5418,7 +5531,7 @@ finish_struct_1 (t)
tree field_vec = make_tree_vec (n_fields);
add_fields_to_vec (TYPE_FIELDS (t), field_vec, 0);
qsort (&TREE_VEC_ELT (field_vec, 0), n_fields, sizeof (tree),
- (int (*)(const void *, const void *))field_decl_cmp);
+ field_decl_cmp);
if (! DECL_LANG_SPECIFIC (TYPE_MAIN_DECL (t)))
retrofit_lang_decl (TYPE_MAIN_DECL (t));
DECL_SORTED_FIELDS (TYPE_MAIN_DECL (t)) = field_vec;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 8f77d10bab7..aad82c019b2 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1,5 +1,5 @@
/* Definitions for C++ parsing and type checking.
- Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2003,
2000, 2001, 2002 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
@@ -23,6 +23,7 @@ Boston, MA 02111-1307, USA. */
#ifndef GCC_CP_TREE_H
#define GCC_CP_TREE_H
+#include "ggc.h"
#include "function.h"
#include "hashtab.h"
#include "splay-tree.h"
@@ -1182,7 +1183,7 @@ struct lang_type_class GTY(())
tree as_base;
tree pure_virtuals;
tree friend_classes;
- tree methods;
+ tree GTY ((reorder ("resort_type_method_vec"))) methods;
tree key_method;
tree decl_list;
tree template_info;
@@ -1782,7 +1783,7 @@ struct lang_decl_flags GTY(())
tree GTY ((tag ("0"))) access;
/* For VAR_DECL in function, this is DECL_DISCRIMINATOR. */
- int discriminator;
+ int GTY ((tag ("1"))) discriminator;
/* In a FUNCTION_DECL for which DECL_THUNK_P holds, this is
THUNK_VIRTUAL_OFFSET. */
@@ -1790,6 +1791,9 @@ struct lang_decl_flags GTY(())
} GTY ((desc ("%1.u2sel"))) u2;
};
+/* sorted_fields is sorted based on a pointer, so we need to be able
+ to resort it if pointers get rearranged. */
+
struct lang_decl GTY(())
{
struct lang_decl_flags decl_flags;
@@ -1827,7 +1831,8 @@ struct lang_decl GTY(())
union lang_decl_u3
{
- tree GTY ((tag ("0"))) sorted_fields;
+ tree GTY ((tag ("0"), reorder ("resort_sorted_fields")))
+ sorted_fields;
struct cp_token_cache * GTY ((tag ("2"))) pending_inline_info;
struct language_function * GTY ((tag ("1")))
saved_language_function;
@@ -3555,7 +3560,7 @@ extern void init_reswords PARAMS ((void));
opname_tab[(int) MINUS_EXPR] == "-". */
extern const char **opname_tab, **assignop_tab;
-typedef struct operator_name_info_t
+typedef struct operator_name_info_t GTY(())
{
/* The IDENTIFIER_NODE for the operator. */
tree identifier;
@@ -3568,9 +3573,11 @@ typedef struct operator_name_info_t
} operator_name_info_t;
/* A mapping from tree codes to operator name information. */
-extern operator_name_info_t operator_name_info[];
+extern GTY(()) operator_name_info_t operator_name_info
+ [(int) LAST_CPLUS_TREE_CODE];
/* Similar, but for assignment operators. */
-extern operator_name_info_t assignment_operator_name_info[];
+extern GTY(()) operator_name_info_t assignment_operator_name_info
+ [(int) LAST_CPLUS_TREE_CODE];
/* in call.c */
extern bool check_dtor_name (tree, tree);
@@ -3611,10 +3618,14 @@ extern tree in_charge_arg_for_name (tree);
/* in class.c */
extern tree build_base_path PARAMS ((enum tree_code, tree, tree, int));
-extern tree convert_to_base (tree, tree, bool);
+extern tree convert_to_base PARAMS ((tree, tree, bool));
extern tree build_vtbl_ref PARAMS ((tree, tree));
extern tree build_vfn_ref PARAMS ((tree, tree));
extern tree get_vtable_decl PARAMS ((tree, int));
+extern void resort_sorted_fields
+ PARAMS ((void *, void *, gt_pointer_operator, void *));
+extern void resort_type_method_vec
+ PARAMS ((void *, void *, gt_pointer_operator, void *));
extern void add_method PARAMS ((tree, tree, int));
extern int currently_open_class PARAMS ((tree));
extern tree currently_open_derived_class PARAMS ((tree));
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 35a14e8cbe0..29a7a7fb93b 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -44,7 +44,6 @@ Boston, MA 02111-1307, USA. */
#include "except.h"
#include "toplev.h"
#include "hashtab.h"
-#include "ggc.h"
#include "tm_p.h"
#include "target.h"
#include "c-common.h"
@@ -2731,7 +2730,7 @@ pushtag (tree name, tree type, int globalize)
/* Counter used to create anonymous type names. */
-static int anon_cnt = 0;
+static GTY(()) int anon_cnt;
/* Return an IDENTIFIER which can be used as a name for
anonymous structs and unions. */
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 6363007b4ef..2491c8a3979 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -42,7 +42,6 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
#include "except.h"
#include "toplev.h"
-#include "ggc.h"
#include "timevar.h"
#include "cpplib.h"
#include "target.h"
@@ -2589,6 +2588,9 @@ finish_file ()
if (! global_bindings_p () || current_class_type || decl_namespace_list)
return;
+ if (pch_file)
+ c_common_write_pch ();
+
/* Otherwise, GDB can get confused, because in only knows
about source for LINENO-1 lines. */
lineno -= 1;
diff --git a/gcc/cp/g++spec.c b/gcc/cp/g++spec.c
index 8c1e3ae98f1..75a1d7c28a4 100644
--- a/gcc/cp/g++spec.c
+++ b/gcc/cp/g++spec.c
@@ -60,14 +60,16 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
/* If nonzero, the user gave us the `-v' flag. */
int saw_verbose_flag = 0;
- /* This will be 0 if we encounter a situation where we should not
- link in libstdc++. */
- int library = 1;
+ /* This is a tristate:
+ -1 means we should not link in libstdc++
+ 0 means we should link in libstdc++ if it is needed
+ 1 means libstdc++ is needed and should be linked in. */
+ int library = 0;
/* The number of arguments being added to what's in argv, other than
libraries. We use this to track the number of times we've inserted
-xc++/-xnone. */
- int added = 2;
+ int added = 0;
/* Used to track options that take arguments, so we don't go wrapping
those with -xc++/-xnone. */
@@ -131,10 +133,10 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
if (argv[i][0] == '-')
{
- if (library != 0 && (strcmp (argv[i], "-nostdlib") == 0
- || strcmp (argv[i], "-nodefaultlibs") == 0))
+ if (strcmp (argv[i], "-nostdlib") == 0
+ || strcmp (argv[i], "-nodefaultlibs") == 0)
{
- library = 0;
+ library = -1;
}
else if (strcmp (argv[i], "-lm") == 0
|| strcmp (argv[i], "-lmath") == 0
@@ -152,31 +154,37 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
else if (strcmp (argv[i], "-pg") == 0 || strcmp (argv[i], "-p") == 0)
saw_profile_flag++;
else if (strcmp (argv[i], "-v") == 0)
+ saw_verbose_flag = 1;
+ else if (strncmp (argv[i], "-x", 2) == 0)
{
- saw_verbose_flag = 1;
- if (argc == 2)
+ if (library == 0)
{
- /* If they only gave us `-v', don't try to link
- in libg++. */
- library = 0;
+ const char * arg;
+ if (argv[i][2] != '\0')
+ arg = argv[i]+2;
+ else if (argv[i+1] != NULL)
+ arg = argv[i+1];
+ else /* Error condition, message will be printed later. */
+ arg = "";
+ if (strcmp (arg, "c++") == 0
+ || strcmp (arg, "c++-cpp-output") == 0)
+ library = 1;
}
+ saw_speclang = 1;
}
- else if (strncmp (argv[i], "-x", 2) == 0)
- saw_speclang = 1;
else if (((argv[i][2] == '\0'
&& (char *)strchr ("bBVDUoeTuIYmLiA", argv[i][1]) != NULL)
|| strcmp (argv[i], "-Xlinker") == 0
|| strcmp (argv[i], "-Tdata") == 0))
quote = argv[i];
- else if (library != 0 && ((argv[i][2] == '\0'
- && (char *) strchr ("cSEM", argv[i][1]) != NULL)
- || strcmp (argv[i], "-MM") == 0
- || strcmp (argv[i], "-fsyntax-only") == 0))
+ else if ((argv[i][2] == '\0'
+ && (char *) strchr ("cSEM", argv[i][1]) != NULL)
+ || strcmp (argv[i], "-MM") == 0
+ || strcmp (argv[i], "-fsyntax-only") == 0)
{
/* Don't specify libraries if we won't link, since that would
cause a warning. */
- library = 0;
- added -= 2;
+ library = -1;
}
else if (strcmp (argv[i], "-static-libgcc") == 0
|| strcmp (argv[i], "-static") == 0)
@@ -195,16 +203,28 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
continue;
}
- /* If the filename ends in .c or .i, put options around it.
+ /* If the filename ends in .[chi], put options around it.
But not if a specified -x option is currently active. */
len = strlen (argv[i]);
if (len > 2
- && (argv[i][len - 1] == 'c' || argv[i][len - 1] == 'i')
+ && (argv[i][len - 1] == 'c'
+ || argv[i][len - 1] == 'i'
+ || argv[i][len - 1] == 'h')
&& argv[i][len - 2] == '.')
{
args[i] |= LANGSPEC;
added += 2;
}
+
+ /* If we don't know that this is a header file, we might
+ need to be linking in the libraries. */
+ if (library == 0)
+ {
+ if ((len <= 2 || strcmp (argv[i] + (len - 2), ".H") != 0)
+ && (len <= 2 || strcmp (argv[i] + (len - 2), ".h") != 0)
+ && (len <= 3 || strcmp (argv[i] + (len - 3), ".hh") != 0))
+ library = 1;
+ }
}
}
@@ -212,7 +232,7 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
fatal ("argument to `%s' missing\n", quote);
/* If we know we don't have to do anything, bail now. */
- if (! added && ! library)
+ if (! added && library <= 0)
{
free (args);
return;
@@ -225,7 +245,7 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
#endif
/* Make sure to have room for the trailing NULL argument. */
- num_args = argc + added + need_math + shared_libgcc + 1;
+ num_args = argc + added + need_math + shared_libgcc + (library > 0) + 1;
arglist = (const char **) xmalloc (num_args * sizeof (char *));
i = 0;
@@ -241,27 +261,37 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
/* Make sure -lstdc++ is before the math library, since libstdc++
itself uses those math routines. */
- if (!saw_math && (args[i] & MATHLIB) && library)
+ if (!saw_math && (args[i] & MATHLIB) && library > 0)
{
--j;
saw_math = argv[i];
}
- if (!saw_libc && (args[i] & WITHLIBC) && library)
+ if (!saw_libc && (args[i] & WITHLIBC) && library > 0)
{
--j;
saw_libc = argv[i];
}
- /* Wrap foo.c and foo.i files in a language specification to
+ /* Wrap foo.[chi] files in a language specification to
force the gcc compiler driver to run cc1plus on them. */
if (args[i] & LANGSPEC)
{
int len = strlen (argv[i]);
- if (argv[i][len - 1] == 'i')
- arglist[j++] = "-xc++-cpp-output";
- else
- arglist[j++] = "-xc++";
+ switch (argv[i][len - 1])
+ {
+ case 'c':
+ arglist[j++] = "-xc++";
+ break;
+ case 'i':
+ arglist[j++] = "-xc++-cpp-output";
+ break;
+ case 'h':
+ arglist[j++] = "-xc++-header";
+ break;
+ default:
+ abort ();
+ }
arglist[j++] = argv[i];
arglist[j] = "-xnone";
}
@@ -271,7 +301,7 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
}
/* Add `-lstdc++' if we haven't already done so. */
- if (library)
+ if (library > 0)
{
arglist[j++] = saw_profile_flag ? LIBSTDCXX_PROFILE : LIBSTDCXX;
added_libraries++;
@@ -285,7 +315,7 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
}
if (saw_math)
arglist[j++] = saw_math;
- else if (library && need_math)
+ else if (library > 0 && need_math)
{
arglist[j++] = saw_profile_flag ? MATH_LIBRARY_PROFILE : MATH_LIBRARY;
added_libraries++;
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 2fd0c50779b..964ee1e0c12 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -34,7 +34,6 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
#include "except.h"
#include "toplev.h"
-#include "ggc.h"
static void construct_virtual_base (tree, tree);
static void expand_aggr_init_1 PARAMS ((tree, tree, tree, tree, int));
diff --git a/gcc/cp/lang-specs.h b/gcc/cp/lang-specs.h
index e8264676449..cf4ca4cee36 100644
--- a/gcc/cp/lang-specs.h
+++ b/gcc/cp/lang-specs.h
@@ -33,6 +33,19 @@ Boston, MA 02111-1307, USA. */
{".c++", "@c++", 0},
{".C", "@c++", 0},
{".CPP", "@c++", 0},
+ {".H", "@c++-header", 0},
+ {".hh", "@c++-header", 0},
+ {"@c++-header",
+ "%{E|M|MM:cc1plus -E %{!no-gcc:-D__GNUG__=%v1}\
+ %(cpp_options) %2 %(cpp_debug_options)}\
+ %{!E:%{!M:%{!MM:\
+ %{save-temps:cc1plus -E %{!no-gcc:-D__GNUG__=%v1}\
+ %(cpp_options) %2 %b.ii \n}\
+ cc1plus %{save-temps:-fpreprocessed %b.ii}\
+ %{!save-temps:%(cpp_unique_options) %{!no-gcc:-D__GNUG__=%v1}}\
+ %(cc1_options) %2 %{+e1*}\
+ -o %g.s %{!o*:--output-pch=%i.pch} %W{o*:--output-pch=%*}%V}}}",
+ CPLUSPLUS_CPP_SPEC},
{"@c++",
"%{E|M|MM:cc1plus -E %{!no-gcc:-D__GNUG__=%v1}\
%(cpp_options) %2 %(cpp_debug_options)}\
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index 29753992b54..5749fc463b7 100644
--- a/gcc/cp/lex.c
+++ b/gcc/cp/lex.c
@@ -36,7 +36,6 @@ Boston, MA 02111-1307, USA. */
#include "c-pragma.h"
#include "toplev.h"
#include "output.h"
-#include "ggc.h"
#include "tm_p.h"
#include "timevar.h"
#include "diagnostic.h"
@@ -380,10 +379,7 @@ init_reswords ()
int mask = ((flag_no_asm ? D_ASM : 0)
| (flag_no_gnu_keywords ? D_EXT : 0));
- /* It is not necessary to register ridpointers as a GC root, because
- all the trees it points to are permanently interned in the
- get_identifier hash anyway. */
- ridpointers = (tree *) xcalloc ((int) RID_MAX, sizeof (tree));
+ ridpointers = (tree *) ggc_calloc ((int) RID_MAX, sizeof (tree));
for (i = 0; i < ARRAY_SIZE (reswords); i++)
{
id = get_identifier (reswords[i].word);
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index f4960b29c53..883a81f73fd 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -1,7 +1,7 @@
/* Handle the hair of processing (but not expanding) inline functions.
Also manage function and variable name overloading.
- Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+ 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC.
@@ -34,7 +34,6 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
#include "flags.h"
#include "toplev.h"
-#include "ggc.h"
#include "tm_p.h"
#include "target.h"
diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c
index fe924f4aae4..8f08c9ac22b 100644
--- a/gcc/cp/optimize.c
+++ b/gcc/cp/optimize.c
@@ -31,7 +31,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "integrate.h"
#include "toplev.h"
#include "varray.h"
-#include "ggc.h"
#include "params.h"
#include "hashtab.h"
#include "debug.h"
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index e88045dc117..629ba5d8178 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -32,7 +32,6 @@
#include "decl.h"
#include "flags.h"
#include "diagnostic.h"
-#include "ggc.h"
#include "toplev.h"
#include "output.h"
@@ -213,8 +212,8 @@ typedef struct cp_lexer GTY (())
/* Prototypes. */
-static cp_lexer *cp_lexer_new
- PARAMS ((bool));
+static cp_lexer *cp_lexer_new_main
+ PARAMS ((void));
static cp_lexer *cp_lexer_new_from_tokens
PARAMS ((struct cp_token_cache *));
static int cp_lexer_saving_tokens
@@ -292,29 +291,37 @@ static void cp_lexer_stop_debugging
/* The stream to which debugging output should be written. */
static FILE *cp_lexer_debug_stream;
-/* Create a new C++ lexer. If MAIN_LEXER_P is true the new lexer is
- the main lexer -- i.e, the lexer that gets tokens from the
- preprocessor. Otherwise, it is a lexer that uses a cache of stored
- tokens. */
+/* Create a new main C++ lexer, the lexer that gets tokens from the
+ preprocessor. */
static cp_lexer *
-cp_lexer_new (bool main_lexer_p)
+cp_lexer_new_main (void)
{
cp_lexer *lexer;
+ cp_token first_token;
+
+ /* It's possible that lexing the first token will load a PCH file,
+ which is a GC collection point. So we have to grab the first
+ token before allocating any memory. */
+ cp_lexer_get_preprocessor_token (NULL, &first_token);
+ cpp_get_callbacks (parse_in)->valid_pch = NULL;
/* Allocate the memory. */
lexer = (cp_lexer *) ggc_alloc_cleared (sizeof (cp_lexer));
/* Create the circular buffer. */
lexer->buffer = ((cp_token *)
- ggc_alloc (CP_TOKEN_BUFFER_SIZE * sizeof (cp_token)));
+ ggc_calloc (CP_TOKEN_BUFFER_SIZE, sizeof (cp_token)));
lexer->buffer_end = lexer->buffer + CP_TOKEN_BUFFER_SIZE;
- /* There are no tokens in the buffer. */
- lexer->last_token = lexer->buffer;
+ /* There is one token in the buffer. */
+ lexer->last_token = lexer->buffer + 1;
+ lexer->first_token = lexer->buffer;
+ lexer->next_token = lexer->buffer;
+ memcpy (lexer->buffer, &first_token, sizeof (cp_token));
/* This lexer obtains more tokens by calling c_lex. */
- lexer->main_lexer_p = main_lexer_p;
+ lexer->main_lexer_p = true;
/* Create the SAVED_TOKENS stack. */
VARRAY_INT_INIT (lexer->saved_tokens, CP_SAVED_TOKENS_SIZE, "saved_tokens");
@@ -339,15 +346,14 @@ cp_lexer_new_from_tokens (cp_token_cache *tokens)
cp_token_block *block;
ptrdiff_t num_tokens;
- /* Create the lexer. */
- lexer = cp_lexer_new (/*main_lexer_p=*/false);
+ /* Allocate the memory. */
+ lexer = (cp_lexer *) ggc_alloc_cleared (sizeof (cp_lexer));
/* Create a new buffer, appropriately sized. */
num_tokens = 0;
for (block = tokens->first; block != NULL; block = block->next)
num_tokens += block->num_tokens;
- lexer->buffer = ((cp_token *)
- ggc_alloc (num_tokens * sizeof (cp_token)));
+ lexer->buffer = ((cp_token *) ggc_alloc (num_tokens * sizeof (cp_token)));
lexer->buffer_end = lexer->buffer + num_tokens;
/* Install the tokens. */
@@ -365,6 +371,18 @@ cp_lexer_new_from_tokens (cp_token_cache *tokens)
/* The buffer is full. */
lexer->last_token = lexer->first_token;
+ /* This lexer doesn't obtain more tokens. */
+ lexer->main_lexer_p = false;
+
+ /* Create the SAVED_TOKENS stack. */
+ VARRAY_INT_INIT (lexer->saved_tokens, CP_SAVED_TOKENS_SIZE, "saved_tokens");
+
+ /* Create the STRINGS array. */
+ VARRAY_TREE_INIT (lexer->string_tokens, 32, "strings");
+
+ /* Assume we are not debugging. */
+ lexer->debugging_p = false;
+
return lexer;
}
@@ -610,7 +628,7 @@ cp_lexer_get_preprocessor_token (lexer, token)
bool done;
/* If this not the main lexer, return a terminating CPP_EOF token. */
- if (!lexer->main_lexer_p)
+ if (lexer != NULL && !lexer->main_lexer_p)
{
token->type = CPP_EOF;
token->line_number = 0;
@@ -2472,9 +2490,14 @@ static cp_parser *
cp_parser_new ()
{
cp_parser *parser;
+ cp_lexer *lexer;
+
+ /* cp_lexer_new_main is called before calling ggc_alloc because
+ cp_lexer_new_main might load a PCH file. */
+ lexer = cp_lexer_new_main ();
parser = (cp_parser *) ggc_alloc_cleared (sizeof (cp_parser));
- parser->lexer = cp_lexer_new (/*main_lexer_p=*/true);
+ parser->lexer = lexer;
parser->context = cp_parser_context_new (NULL);
/* For now, we always accept GNU extensions. */
@@ -14422,9 +14445,7 @@ cp_parser_late_parsing_for_member (parser, member_function)
/* Set the current source position to be the location of the first
token in the saved inline body. */
- cp_lexer_set_source_position_from_token
- (parser->lexer,
- cp_lexer_peek_token (parser->lexer));
+ (void) cp_lexer_peek_token (parser->lexer);
/* Let the front end know that we going to be defining this
function. */
@@ -14477,8 +14498,7 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
/* Set the current source position to be the location of the
first token in the default argument. */
- cp_lexer_set_source_position_from_token
- (parser->lexer, cp_lexer_peek_token (parser->lexer));
+ (void) cp_lexer_peek_token (parser->lexer);
/* Local variable names (and the `this' keyword) may not appear
in a default argument. */
@@ -14996,6 +15016,8 @@ yyparse ()
the_parser = cp_parser_new ();
error_occurred = cp_parser_translation_unit (the_parser);
the_parser = NULL;
+
+ finish_file ();
return error_occurred;
}
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 7802e25b573..e7486afca25 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -41,7 +41,6 @@ Boston, MA 02111-1307, USA. */
#include "except.h"
#include "toplev.h"
#include "rtl.h"
-#include "ggc.h"
#include "timevar.h"
/* The type of functions taking a tree, and some additional data, and
diff --git a/gcc/cp/repo.c b/gcc/cp/repo.c
index 105e4df51ac..603b04eef06 100644
--- a/gcc/cp/repo.c
+++ b/gcc/cp/repo.c
@@ -35,7 +35,6 @@ Boston, MA 02111-1307, USA. */
#include "input.h"
#include "obstack.h"
#include "toplev.h"
-#include "ggc.h"
#include "diagnostic.h"
static tree repo_get_id (tree);
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 13ed4b0aa53..5e9b3955ad4 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -33,7 +33,6 @@ Boston, MA 02111-1307, USA. */
#include "flags.h"
#include "rtl.h"
#include "output.h"
-#include "ggc.h"
#include "toplev.h"
#include "stack.h"
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 0aeaa0db77e..3ed9f2e20a3 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -3,7 +3,7 @@
building RTL. These routines are used both during actual parsing
and during the instantiation of template functions.
- Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Written by Mark Mitchell (mmitchell@usa.net) based on code found
formerly in parse.y and pt.c.
@@ -35,7 +35,6 @@
#include "lex.h"
#include "toplev.h"
#include "flags.h"
-#include "ggc.h"
#include "rtl.h"
#include "expr.h"
#include "output.h"
@@ -1628,8 +1627,6 @@ finish_translation_unit ()
/* Do file scope __FUNCTION__ et al. */
finish_fname_decls ();
-
- finish_file ();
}
/* Finish a template type parameter, specified as AGGR IDENTIFIER.
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 93c62dac158..a3b6ff14a4f 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -30,7 +30,6 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "rtl.h"
#include "toplev.h"
-#include "ggc.h"
#include "insn-config.h"
#include "integrate.h"
#include "tree-inline.h"
diff --git a/gcc/cppfiles.c b/gcc/cppfiles.c
index 4d8219661d0..203619f30b8 100644
--- a/gcc/cppfiles.c
+++ b/gcc/cppfiles.c
@@ -22,6 +22,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include <dirent.h>
#include "coretypes.h"
#include "tm.h"
#include "cpplib.h"
@@ -87,6 +88,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* This structure is used for the table of all includes. */
struct include_file {
const char *name; /* actual path name of file */
+ const char *header_name; /* the original header found */
const cpp_hashnode *cmacro; /* macro, if any, preventing reinclusion. */
const struct search_path *foundhere;
/* location in search path where file was
@@ -98,6 +100,13 @@ struct include_file {
unsigned short include_count; /* number of times file has been read */
unsigned short refcnt; /* number of stacked buffers using this file */
unsigned char mapped; /* file buffer is mmapped */
+ unsigned char pch; /* 0: file not known to be a PCH.
+ 1: file is a PCH
+ (on return from find_include_file).
+ 2: file is not and never will be a valid
+ precompiled header.
+ 3: file is always a valid precompiled
+ header. */
};
/* Variable length record files on VMS will have a stat size that includes
@@ -118,6 +127,7 @@ struct include_file {
((inc)->cmacro && ((inc)->cmacro == NEVER_REREAD \
|| (inc)->cmacro->type == NT_MACRO))
#define NO_INCLUDE_PATH ((struct include_file *) -1)
+#define INCLUDE_PCH_P(F) (((F)->pch & 1) != 0)
static struct file_name_map *read_name_map
PARAMS ((cpp_reader *, const char *));
@@ -130,6 +140,11 @@ static struct include_file *
find_include_file PARAMS ((cpp_reader *, const cpp_token *,
enum include_type));
static struct include_file *open_file PARAMS ((cpp_reader *, const char *));
+static struct include_file *validate_pch PARAMS ((cpp_reader *,
+ const char *,
+ const char *));
+static struct include_file *open_file_pch PARAMS ((cpp_reader *,
+ const char *));
static int read_include_file PARAMS ((cpp_reader *, struct include_file *));
static bool stack_include_file PARAMS ((cpp_reader *, struct include_file *));
static void purge_cache PARAMS ((struct include_file *));
@@ -212,6 +227,7 @@ find_or_create_entry (pfile, fname)
{
file = xcnew (struct include_file);
file->name = name;
+ file->header_name = name;
file->err_no = errno;
node = splay_tree_insert (pfile->all_include_files,
(splay_tree_key) file->name,
@@ -306,6 +322,89 @@ open_file (pfile, filename)
return 0;
}
+static struct include_file *
+validate_pch (pfile, filename, pchname)
+ cpp_reader *pfile;
+ const char *filename;
+ const char *pchname;
+{
+ struct include_file * file;
+
+ file = open_file (pfile, pchname);
+ if (file == NULL)
+ return NULL;
+ if ((file->pch & 2) == 0)
+ file->pch = pfile->cb.valid_pch (pfile, pchname, file->fd);
+ if (INCLUDE_PCH_P (file))
+ {
+ file->header_name = _cpp_simplify_pathname (xstrdup (filename));
+ return file;
+ }
+ close (file->fd);
+ file->fd = -1;
+ return NULL;
+}
+
+
+/* Like open_file, but also look for a precompiled header if (a) one exists
+ and (b) it is valid. */
+static struct include_file *
+open_file_pch (pfile, filename)
+ cpp_reader *pfile;
+ const char *filename;
+{
+ if (filename[0] != '\0'
+ && pfile->cb.valid_pch != NULL)
+ {
+ size_t namelen = strlen (filename);
+ char *pchname = alloca (namelen + 5);
+ struct include_file * file;
+ splay_tree_node nd;
+
+ memcpy (pchname, filename, namelen);
+ memcpy (pchname + namelen, ".pch", 5);
+
+ nd = find_or_create_entry (pfile, pchname);
+ file = (struct include_file *) nd->value;
+
+ if (file != NULL)
+ {
+ if (stat (file->name, &file->st) == 0 && S_ISDIR (file->st.st_mode))
+ {
+ DIR * thedir;
+ struct dirent *d;
+ size_t subname_len = namelen + 64;
+ char *subname = xmalloc (subname_len);
+
+ thedir = opendir (pchname);
+ if (thedir == NULL)
+ return NULL;
+ memcpy (subname, pchname, namelen + 4);
+ subname[namelen+4] = '/';
+ while ((d = readdir (thedir)) != NULL)
+ {
+ if (strlen (d->d_name) + namelen + 7 > subname_len)
+ {
+ subname_len = strlen (d->d_name) + namelen + 64;
+ subname = xrealloc (subname, subname_len);
+ }
+ strcpy (subname + namelen + 5, d->d_name);
+ file = validate_pch (pfile, filename, subname);
+ if (file)
+ break;
+ }
+ closedir (thedir);
+ free (subname);
+ }
+ else
+ file = validate_pch (pfile, filename, pchname);
+ if (file)
+ return file;
+ }
+ }
+ return open_file (pfile, filename);
+}
+
/* Place the file referenced by INC into a new buffer on the buffer
stack, unless there are errors, or the file is not re-included
because of e.g. multiple-include guards. Returns true if a buffer
@@ -332,6 +431,15 @@ stack_include_file (pfile, inc)
deps_add_dep (pfile->deps, inc->name);
}
+ /* PCH files get dealt with immediately. */
+ if (INCLUDE_PCH_P (inc))
+ {
+ pfile->cb.read_pch (pfile, inc->name, inc->fd, inc->header_name);
+ close (inc->fd);
+ inc->fd = -1;
+ return false;
+ }
+
/* Not in cache? */
if (! inc->buffer)
{
@@ -579,7 +687,7 @@ find_include_file (pfile, header, type)
char *name, *n;
if (IS_ABSOLUTE_PATHNAME (fname))
- return open_file (pfile, fname);
+ return open_file_pch (pfile, fname);
/* For #include_next, skip in the search path past the dir in which
the current file was found, but if it was found via an absolute
@@ -615,7 +723,7 @@ find_include_file (pfile, header, type)
else
n = name;
- file = open_file (pfile, n);
+ file = open_file_pch (pfile, n);
if (file)
{
file->foundhere = path;
@@ -757,6 +865,9 @@ _cpp_read_file (pfile, fname)
cpp_reader *pfile;
const char *fname;
{
+ /* This uses open_file, because we don't allow a PCH to be used as
+ the toplevel compilation (that would prevent re-compiling an
+ existing PCH without deleting it first). */
struct include_file *f = open_file (pfile, fname);
if (f == NULL)
diff --git a/gcc/cpphash.h b/gcc/cpphash.h
index 16e8dfe08fe..d5a0b5d155a 100644
--- a/gcc/cpphash.h
+++ b/gcc/cpphash.h
@@ -449,6 +449,10 @@ struct cpp_reader
/* Used to save the original line number during traditional
preprocessing. */
unsigned int saved_line;
+
+ /* A saved list of the defined macros, for dependency checking
+ of precompiled headers. */
+ struct cpp_savedstate *savedstate;
};
/* Character classes. Based on the more primitive macros in safe-ctype.h.
@@ -542,6 +546,8 @@ extern void _cpp_maybe_push_include_file PARAMS ((cpp_reader *));
extern int _cpp_test_assertion PARAMS ((cpp_reader *, unsigned int *));
extern int _cpp_handle_directive PARAMS ((cpp_reader *, int));
extern void _cpp_define_builtin PARAMS ((cpp_reader *, const char *));
+extern char ** _cpp_save_pragma_names PARAMS ((cpp_reader *));
+extern void _cpp_restore_pragma_names PARAMS ((cpp_reader *, char **));
extern void _cpp_do__Pragma PARAMS ((cpp_reader *));
extern void _cpp_init_directives PARAMS ((cpp_reader *));
extern void _cpp_init_internal_pragmas PARAMS ((cpp_reader *));
diff --git a/gcc/cpplib.c b/gcc/cpplib.c
index e032e75bef5..1019a2a9713 100644
--- a/gcc/cpplib.c
+++ b/gcc/cpplib.c
@@ -121,6 +121,11 @@ static struct pragma_entry *lookup_pragma_entry
static struct pragma_entry *insert_pragma_entry
PARAMS ((cpp_reader *, struct pragma_entry **, const cpp_hashnode *,
pragma_cb));
+static int count_registered_pragmas PARAMS ((struct pragma_entry *));
+static char ** save_registered_pragmas
+ PARAMS ((struct pragma_entry *, char **));
+static char ** restore_registered_pragmas
+ PARAMS ((cpp_reader *, struct pragma_entry *, char **));
static void do_pragma_once PARAMS ((cpp_reader *));
static void do_pragma_poison PARAMS ((cpp_reader *));
static void do_pragma_system_header PARAMS ((cpp_reader *));
@@ -1085,6 +1090,85 @@ _cpp_init_internal_pragmas (pfile)
cpp_register_pragma (pfile, "GCC", "dependency", do_pragma_dependency);
}
+/* Return the number of registered pragmas in PE. */
+
+static int
+count_registered_pragmas (pe)
+ struct pragma_entry *pe;
+{
+ int ct = 0;
+ for (; pe != NULL; pe = pe->next)
+ {
+ if (pe->is_nspace)
+ ct += count_registered_pragmas (pe->u.space);
+ ct++;
+ }
+ return ct;
+}
+
+/* Save into SD the names of the registered pragmas referenced by PE,
+ and return a pointer to the next free space in SD. */
+
+static char **
+save_registered_pragmas (pe, sd)
+ struct pragma_entry *pe;
+ char **sd;
+{
+ for (; pe != NULL; pe = pe->next)
+ {
+ if (pe->is_nspace)
+ sd = save_registered_pragmas (pe->u.space, sd);
+ *sd++ = xmemdup (HT_STR (&pe->pragma->ident),
+ HT_LEN (&pe->pragma->ident),
+ HT_LEN (&pe->pragma->ident) + 1);
+ }
+ return sd;
+}
+
+/* Return a newly-allocated array which saves the names of the
+ registered pragmas. */
+
+char **
+_cpp_save_pragma_names (pfile)
+ cpp_reader *pfile;
+{
+ int ct = count_registered_pragmas (pfile->pragmas);
+ char **result = xnewvec (char *, ct);
+ (void) save_registered_pragmas (pfile->pragmas, result);
+ return result;
+}
+
+/* Restore from SD the names of the registered pragmas referenced by PE,
+ and return a pointer to the next unused name in SD. */
+
+static char **
+restore_registered_pragmas (pfile, pe, sd)
+ cpp_reader *pfile;
+ struct pragma_entry *pe;
+ char **sd;
+{
+ for (; pe != NULL; pe = pe->next)
+ {
+ if (pe->is_nspace)
+ sd = restore_registered_pragmas (pfile, pe->u.space, sd);
+ pe->pragma = cpp_lookup (pfile, U *sd, strlen (*sd));
+ free (*sd);
+ sd++;
+ }
+ return sd;
+}
+
+/* Restore the names of the registered pragmas from SAVED. */
+
+void
+_cpp_restore_pragma_names (pfile, saved)
+ cpp_reader *pfile;
+ char **saved;
+{
+ (void) restore_registered_pragmas (pfile, pfile->pragmas, saved);
+ free (saved);
+}
+
/* Pragmata handling. We handle some, and pass the rest on to the
front end. C99 defines three pragmas and says that no macro
expansion is to be performed on them; whether or not macro
diff --git a/gcc/cpplib.h b/gcc/cpplib.h
index 271a75531e9..bccfecf86be 100644
--- a/gcc/cpplib.h
+++ b/gcc/cpplib.h
@@ -400,6 +400,12 @@ struct cpp_options
/* Nonzero means __STDC__ should have the value 0 in system headers. */
unsigned char stdc_0_in_system_headers;
+
+ /* True to warn about precompiled header files we couldn't use. */
+ bool warn_invalid_pch;
+
+ /* True if dependencies should be restored from a precompiled header. */
+ bool restore_pch_deps;
};
/* Call backs. */
@@ -417,6 +423,8 @@ struct cpp_callbacks
/* Called when the client has a chance to properly register
built-ins with cpp_define() and cpp_assert(). */
void (*register_builtins) PARAMS ((cpp_reader *));
+ int (*valid_pch) PARAMS ((cpp_reader *, const char *, int));
+ void (*read_pch) PARAMS ((cpp_reader *, const char *, int, const char *));
};
/* Name under which this program was invoked. */
@@ -472,7 +480,7 @@ enum builtin_type
/* The common part of an identifier node shared amongst all 3 C front
ends. Also used to store CPP identifiers, which are a superset of
identifiers in the grammatical sense. */
-struct cpp_hashnode
+struct cpp_hashnode GTY(())
{
struct ht_identifier ident;
unsigned int is_directive : 1;
@@ -485,11 +493,15 @@ struct cpp_hashnode
union _cpp_hashnode_value
{
- cpp_macro *macro; /* If a macro. */
- struct answer *answers; /* Answers to an assertion. */
- enum builtin_type builtin; /* Code for a builtin macro. */
- unsigned short arg_index; /* Macro argument index. */
- } value;
+ /* If a macro. */
+ cpp_macro * GTY((skip (""))) macro;
+ /* Answers to an assertion. */
+ struct answer * GTY ((skip (""))) answers;
+ /* Code for a builtin macro. */
+ enum builtin_type GTY ((tag ("1"))) builtin;
+ /* Macro argument index. */
+ unsigned short GTY ((tag ("0"))) arg_index;
+ } GTY ((desc ("0"))) value;
};
/* Call this first to get a handle to pass to other functions. */
@@ -722,6 +734,17 @@ extern unsigned char *cpp_quote_string PARAMS ((unsigned char *,
extern int cpp_included PARAMS ((cpp_reader *, const char *));
extern void cpp_make_system_header PARAMS ((cpp_reader *, int, int));
+/* In cpppch.c */
+struct save_macro_data;
+extern int cpp_save_state PARAMS ((cpp_reader *, FILE *));
+extern int cpp_write_pch_deps PARAMS ((cpp_reader *, FILE *));
+extern int cpp_write_pch_state PARAMS ((cpp_reader *, FILE *));
+extern int cpp_valid_state PARAMS ((cpp_reader *, const char *, int));
+extern void cpp_prepare_state PARAMS ((cpp_reader *,
+ struct save_macro_data **));
+extern int cpp_read_state PARAMS ((cpp_reader *, const char *, FILE *,
+ struct save_macro_data *));
+
/* In cppmain.c */
extern void cpp_preprocess_file PARAMS ((cpp_reader *, const char *, FILE *));
diff --git a/gcc/cpppch.c b/gcc/cpppch.c
new file mode 100644
index 00000000000..e7f0c91adfd
--- /dev/null
+++ b/gcc/cpppch.c
@@ -0,0 +1,684 @@
+/* Part of CPP library. (Precompiled header reading/writing.)
+ Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "cpplib.h"
+#include "cpphash.h"
+#include "intl.h"
+#include "hashtab.h"
+#include "mkdeps.h"
+
+static int write_macdef PARAMS ((cpp_reader *, cpp_hashnode *, void *));
+static int save_idents PARAMS ((cpp_reader *, cpp_hashnode *, void *));
+static hashval_t hashmem PARAMS ((const void *, size_t));
+static hashval_t cpp_string_hash PARAMS ((const void *));
+static int cpp_string_eq PARAMS ((const void *, const void *));
+static int count_defs PARAMS ((cpp_reader *, cpp_hashnode *, void *));
+static int write_defs PARAMS ((cpp_reader *, cpp_hashnode *, void *));
+static int save_macros PARAMS ((cpp_reader *, cpp_hashnode *, void *));
+static int reset_ht PARAMS ((cpp_reader *, cpp_hashnode *, void *));
+
+/* This structure represents a macro definition on disk. */
+struct macrodef_struct
+{
+ unsigned int definition_length;
+ unsigned short name_length;
+ unsigned short flags;
+};
+
+/* This is how we write out a macro definition.
+ Suitable for being called by cpp_forall_identifiers. */
+
+static int
+write_macdef (pfile, hn, file_p)
+ cpp_reader *pfile;
+ cpp_hashnode *hn;
+ void *file_p;
+{
+ FILE *f = (FILE *) file_p;
+ switch (hn->type)
+ {
+ case NT_VOID:
+ if (! (hn->flags & NODE_POISONED))
+ return 1;
+
+ case NT_MACRO:
+ if ((hn->flags & NODE_BUILTIN))
+ return 1;
+
+ {
+ struct macrodef_struct s;
+ const unsigned char *defn;
+
+ s.name_length = NODE_LEN (hn);
+ s.flags = hn->flags & NODE_POISONED;
+
+ if (hn->type == NT_MACRO)
+ {
+ defn = cpp_macro_definition (pfile, hn);
+ s.definition_length = ustrlen (defn);
+ }
+ else
+ {
+ defn = NODE_NAME (hn);
+ s.definition_length = s.name_length;
+ }
+
+ if (fwrite (&s, sizeof (s), 1, f) != 1
+ || fwrite (defn, 1, s.definition_length, f) != s.definition_length)
+ {
+ cpp_errno (pfile, DL_ERROR, "while writing precompiled header");
+ return 0;
+ }
+ }
+ return 1;
+
+ case NT_ASSERTION:
+ /* Not currently implemented. */
+ return 1;
+
+ default:
+ abort ();
+ }
+}
+
+/* This structure records the names of the defined macros.
+ It's also used as a callback structure for size_initial_idents
+ and save_idents. */
+
+struct cpp_savedstate
+{
+ /* A hash table of the defined identifiers. */
+ htab_t definedhash;
+ /* The size of the definitions of those identifiers (the size of
+ 'definedstrs'). */
+ size_t hashsize;
+ /* Space for the next definition. Definitions are null-terminated
+ strings. */
+ unsigned char *definedstrs;
+};
+
+/* Save this identifier into the state: put it in the hash table,
+ put the definition in 'definedstrs'. */
+
+static int
+save_idents (pfile, hn, ss_p)
+ cpp_reader *pfile ATTRIBUTE_UNUSED;
+ cpp_hashnode *hn;
+ void *ss_p;
+{
+ struct cpp_savedstate *const ss = (struct cpp_savedstate *)ss_p;
+
+ if (hn->type != NT_VOID)
+ {
+ struct cpp_string news;
+ void **slot;
+
+ news.len = NODE_LEN (hn);
+ news.text= NODE_NAME (hn);
+ slot = htab_find_slot (ss->definedhash, &news, INSERT);
+ if (*slot == NULL)
+ {
+ struct cpp_string *sp;
+ unsigned char *text;
+
+ sp = xmalloc (sizeof (struct cpp_string));
+ *slot = sp;
+
+ sp->len = NODE_LEN (hn);
+ sp->text = text = xmalloc (NODE_LEN (hn));
+ memcpy (text, NODE_NAME (hn), NODE_LEN (hn));
+ }
+ }
+
+ return 1;
+}
+
+/* Hash some memory in a generic way. */
+
+static hashval_t
+hashmem (p_p, sz)
+ const void *p_p;
+ size_t sz;
+{
+ const unsigned char *p = (const unsigned char *)p_p;
+ size_t i;
+ hashval_t h;
+
+ h = 0;
+ for (i = 0; i < sz; i++)
+ h = h * 67 - (*p++ - 113);
+ return h;
+}
+
+/* Hash a cpp string for the hashtable machinery. */
+
+static hashval_t
+cpp_string_hash (a_p)
+ const void *a_p;
+{
+ const struct cpp_string *a = (const struct cpp_string *) a_p;
+ return hashmem (a->text, a->len);
+}
+
+/* Compare two cpp strings for the hashtable machinery. */
+
+static int
+cpp_string_eq (a_p, b_p)
+ const void *a_p;
+ const void *b_p;
+{
+ const struct cpp_string *a = (const struct cpp_string *) a_p;
+ const struct cpp_string *b = (const struct cpp_string *) b_p;
+ return (a->len == b->len
+ && memcmp (a->text, b->text, a->len) == 0);
+}
+
+/* Save the current definitions of the cpp_reader for dependency
+ checking purposes. When writing a precompiled header, this should
+ be called at the same point in the compilation as cpp_valid_state
+ would be called when reading the precompiled header back in. */
+
+int
+cpp_save_state (r, f)
+ cpp_reader *r;
+ FILE *f;
+{
+ /* Save the list of non-void identifiers for the dependency checking. */
+ r->savedstate = xmalloc (sizeof (struct cpp_savedstate));
+ r->savedstate->definedhash = htab_create (100, cpp_string_hash,
+ cpp_string_eq, NULL);
+ cpp_forall_identifiers (r, save_idents, r->savedstate);
+
+ /* Write out the list of defined identifiers. */
+ cpp_forall_identifiers (r, write_macdef, f);
+
+ return 0;
+}
+
+/* Calculate the 'hashsize' field of the saved state. */
+
+static int
+count_defs (pfile, hn, ss_p)
+ cpp_reader *pfile ATTRIBUTE_UNUSED;
+ cpp_hashnode *hn;
+ void *ss_p;
+{
+ struct cpp_savedstate *const ss = (struct cpp_savedstate *)ss_p;
+
+ switch (hn->type)
+ {
+ case NT_MACRO:
+ if (hn->flags & NODE_BUILTIN)
+ return 1;
+
+ /* else fall through. */
+
+ case NT_VOID:
+ {
+ struct cpp_string news;
+ void **slot;
+
+ news.len = NODE_LEN (hn);
+ news.text = NODE_NAME (hn);
+ slot = htab_find (ss->definedhash, &news);
+ if (slot == NULL)
+ ss->hashsize += NODE_LEN (hn) + 1;
+ }
+ return 1;
+
+ case NT_ASSERTION:
+ /* Not currently implemented. */
+ return 1;
+
+ default:
+ abort ();
+ }
+}
+
+/* Write the identifiers into 'definedstrs' of the state. */
+
+static int
+write_defs (pfile, hn, ss_p)
+ cpp_reader *pfile ATTRIBUTE_UNUSED;
+ cpp_hashnode *hn;
+ void *ss_p;
+{
+ struct cpp_savedstate *const ss = (struct cpp_savedstate *)ss_p;
+
+ switch (hn->type)
+ {
+ case NT_MACRO:
+ if (hn->flags & NODE_BUILTIN)
+ return 1;
+
+ /* else fall through. */
+
+ case NT_VOID:
+ {
+ struct cpp_string news;
+ void **slot;
+
+ news.len = NODE_LEN (hn);
+ news.text = NODE_NAME (hn);
+ slot = htab_find (ss->definedhash, &news);
+ if (slot == NULL)
+ {
+ memcpy (ss->definedstrs, NODE_NAME (hn), NODE_LEN (hn));
+ ss->definedstrs[NODE_LEN (hn)] = 0;
+ ss->definedstrs += NODE_LEN (hn) + 1;
+ }
+ }
+ return 1;
+
+ case NT_ASSERTION:
+ /* Not currently implemented. */
+ return 1;
+
+ default:
+ abort ();
+ }
+}
+
+/* Write out the remainder of the dependency information. This should be
+ called after the PCH is ready to be saved. */
+
+int
+cpp_write_pch_deps (r, f)
+ cpp_reader *r;
+ FILE *f;
+{
+ struct macrodef_struct z;
+ struct cpp_savedstate *const ss = r->savedstate;
+ unsigned char *definedstrs;
+
+ ss->hashsize = 0;
+
+ /* Write out the list of identifiers which have been seen and
+ weren't defined to anything previously. */
+ cpp_forall_identifiers (r, count_defs, ss);
+ definedstrs = ss->definedstrs = xmalloc (ss->hashsize);
+ cpp_forall_identifiers (r, write_defs, ss);
+ memset (&z, 0, sizeof (z));
+ z.definition_length = ss->hashsize;
+ if (fwrite (&z, sizeof (z), 1, f) != 1
+ || fwrite (definedstrs, ss->hashsize, 1, f) != 1)
+ {
+ cpp_errno (r, DL_ERROR, "while writing precompiled header");
+ return -1;
+ }
+ free (definedstrs);
+
+ /* Free the saved state. */
+ free (ss);
+ r->savedstate = NULL;
+ return 0;
+}
+
+/* Write out the definitions of the preprocessor, in a form suitable for
+ cpp_read_state. */
+
+int
+cpp_write_pch_state (r, f)
+ cpp_reader *r;
+ FILE *f;
+{
+ struct macrodef_struct z;
+
+ /* Write out the list of defined identifiers. */
+ cpp_forall_identifiers (r, write_macdef, f);
+ memset (&z, 0, sizeof (z));
+ if (fwrite (&z, sizeof (z), 1, f) != 1)
+ {
+ cpp_errno (r, DL_ERROR, "while writing precompiled header");
+ return -1;
+ }
+
+ if (!r->deps)
+ r->deps = deps_init ();
+
+ if (deps_save (r->deps, f) != 0)
+ {
+ cpp_errno (r, DL_ERROR, "while writing precompiled header");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Return nonzero if FD is a precompiled header which is consistent
+ with the preprocessor's current definitions. It will be consistent
+ when:
+
+ - anything that was defined just before the PCH was generated
+ is defined the same way now; and
+ - anything that was not defined then, but is defined now, was not
+ used by the PCH.
+
+ NAME is used to print warnings if `warn_invalid_pch' is set in the
+ reader's flags.
+*/
+
+int
+cpp_valid_state (r, name, fd)
+ cpp_reader *r;
+ const char *name;
+ int fd;
+{
+ struct macrodef_struct m;
+ size_t namebufsz = 256;
+ unsigned char *namebuf = xmalloc (namebufsz);
+ unsigned char *undeftab = NULL;
+ unsigned int i;
+
+ /* Read in the list of identifiers that must be defined
+ Check that they are defined in the same way. */
+ for (;;)
+ {
+ cpp_hashnode *h;
+ const unsigned char *newdefn;
+
+ if (read (fd, &m, sizeof (m)) != sizeof (m))
+ goto error;
+
+ if (m.name_length == 0)
+ break;
+
+ if (m.definition_length > namebufsz)
+ {
+ free (namebuf);
+ namebufsz = m.definition_length + 256;
+ namebuf = xmalloc (namebufsz);
+ }
+
+ if ((size_t)read (fd, namebuf, m.definition_length)
+ != m.definition_length)
+ goto error;
+
+ h = cpp_lookup (r, namebuf, m.name_length);
+ if (m.flags & NODE_POISONED
+ || h->type != NT_MACRO
+ || h->flags & NODE_POISONED)
+ {
+ if (CPP_OPTION (r, warn_invalid_pch))
+ cpp_error (r, DL_WARNING,
+ "%s: not used because `%.*s' not defined",
+ name, m.name_length, namebuf);
+ goto fail;
+ }
+
+ newdefn = cpp_macro_definition (r, h);
+
+ if (m.definition_length != ustrlen (newdefn)
+ || memcmp (namebuf, newdefn, m.definition_length) != 0)
+ {
+ if (CPP_OPTION (r, warn_invalid_pch))
+ cpp_error (r, DL_WARNING,
+ "%s: not used because `%.*s' defined as `%s' not `%.*s'",
+ name, m.name_length, namebuf, newdefn + m.name_length,
+ m.definition_length - m.name_length,
+ namebuf + m.name_length);
+ goto fail;
+ }
+ }
+ free (namebuf);
+ namebuf = NULL;
+
+ /* Read in the list of identifiers that must not be defined.
+ Check that they really aren't. */
+ undeftab = xmalloc (m.definition_length);
+ if ((size_t) read (fd, undeftab, m.definition_length) != m.definition_length)
+ goto error;
+ for (i = 0; i < m.definition_length; )
+ {
+ int l = ustrlen (undeftab + i);
+ cpp_hashnode *h;
+ h = cpp_lookup (r, undeftab + i, l);
+ if (h->type != NT_VOID
+ || h->flags & NODE_POISONED)
+ {
+ if (CPP_OPTION (r, warn_invalid_pch))
+ cpp_error (r, DL_WARNING, "%s: not used because `%s' is defined",
+ name, undeftab + i);
+ goto fail;
+ }
+ i += l + 1;
+ }
+ free (undeftab);
+
+ /* We win! */
+ return 0;
+
+ error:
+ cpp_errno (r, DL_ERROR, "while reading precompiled header");
+ return -1;
+
+ fail:
+ if (namebuf != NULL)
+ free (namebuf);
+ if (undeftab != NULL)
+ free (undeftab);
+ return 1;
+}
+
+/* Save all the existing macros and assertions.
+ This code assumes that there might be hundreds, but not thousands of
+ existing definitions. */
+
+struct save_macro_item {
+ struct save_macro_item *next;
+ struct cpp_hashnode macs[64];
+};
+
+struct save_macro_data
+{
+ struct save_macro_item *macros;
+ size_t count;
+ char **saved_pragmas;
+};
+
+/* Save the definition of a single macro, so that it will persist across
+ a PCH restore. */
+
+static int
+save_macros (r, h, data_p)
+ cpp_reader *r ATTRIBUTE_UNUSED;
+ cpp_hashnode *h;
+ void *data_p;
+{
+ struct save_macro_data *data = (struct save_macro_data *)data_p;
+ if (h->type != NT_VOID
+ && (h->flags & NODE_BUILTIN) == 0)
+ {
+ cpp_hashnode *save;
+ if (data->count == ARRAY_SIZE (data->macros->macs))
+ {
+ struct save_macro_item *d = data->macros;
+ data->macros = xmalloc (sizeof (struct save_macro_item));
+ data->macros->next = d;
+ data->count = 0;
+ }
+ save = data->macros->macs + data->count;
+ data->count++;
+ memcpy (save, h, sizeof (struct cpp_hashnode));
+ HT_STR (&save->ident) = xmemdup (HT_STR (HT_NODE (save)),
+ HT_LEN (HT_NODE (save)),
+ HT_LEN (HT_NODE (save)) + 1);
+ }
+ return 1;
+}
+
+/* Prepare to restore the state, by saving the currently-defined
+ macros in 'data'. */
+
+void
+cpp_prepare_state (r, data)
+ cpp_reader *r;
+ struct save_macro_data **data;
+{
+ struct save_macro_data *d = xmalloc (sizeof (struct save_macro_data));
+
+ d->macros = NULL;
+ d->count = ARRAY_SIZE (d->macros->macs);
+ cpp_forall_identifiers (r, save_macros, d);
+ d->saved_pragmas = _cpp_save_pragma_names (r);
+ *data = d;
+}
+
+/* Erase all the existing macros and assertions. */
+
+static int
+reset_ht (r, h, unused)
+ cpp_reader *r ATTRIBUTE_UNUSED;
+ cpp_hashnode *h;
+ void *unused ATTRIBUTE_UNUSED;
+{
+ if (h->type != NT_VOID
+ && (h->flags & NODE_BUILTIN) == 0)
+ {
+ h->type = NT_VOID;
+ memset (&h->value, 0, sizeof (h->value));
+ }
+ return 1;
+}
+
+/* Given a precompiled header that was previously determined to be valid,
+ apply all its definitions (and undefinitions) to the current state.
+ DEPNAME is passed to deps_restore. */
+
+int
+cpp_read_state (r, name, f, data)
+ cpp_reader *r;
+ const char *name;
+ FILE *f;
+ struct save_macro_data *data;
+{
+ struct macrodef_struct m;
+ size_t defnlen = 256;
+ unsigned char *defn = xmalloc (defnlen);
+ struct lexer_state old_state;
+ struct save_macro_item *d;
+ size_t i, mac_count;
+ int saved_line = r->line;
+
+ /* Erase all the existing hashtable entries for macros. At this
+ point, they're all from the PCH file, and their pointers won't be
+ valid. */
+ cpp_forall_identifiers (r, reset_ht, NULL);
+
+ /* Restore spec_nodes, which will be full of references to the old
+ hashtable entries and so will now be invalid. */
+ {
+ struct spec_nodes *s = &r->spec_nodes;
+ s->n_defined = cpp_lookup (r, DSC("defined"));
+ s->n_true = cpp_lookup (r, DSC("true"));
+ s->n_false = cpp_lookup (r, DSC("false"));
+ s->n__VA_ARGS__ = cpp_lookup (r, DSC("__VA_ARGS__"));
+ }
+
+ /* Run through the carefully-saved macros, insert them. */
+ d = data->macros;
+ mac_count = data->count;
+ while (d)
+ {
+ struct save_macro_item *nextd;
+ for (i = 0; i < mac_count; i++)
+ {
+ cpp_hashnode *h;
+
+ h = cpp_lookup (r, HT_STR (HT_NODE (&d->macs[i])),
+ HT_LEN (HT_NODE (&d->macs[i])));
+ h->type = d->macs[i].type;
+ h->flags = d->macs[i].flags;
+ h->value = d->macs[i].value;
+ free ((void *)HT_STR (HT_NODE (&d->macs[i])));
+ }
+ nextd = d->next;
+ free (d);
+ d = nextd;
+ mac_count = ARRAY_SIZE (d->macs);
+ }
+
+ _cpp_restore_pragma_names (r, data->saved_pragmas);
+
+ free (data);
+
+ old_state = r->state;
+
+ r->state.in_directive = 1;
+ r->state.prevent_expansion = 1;
+ r->state.angled_headers = 0;
+
+ /* Read in the identifiers that must be defined. */
+ for (;;)
+ {
+ cpp_hashnode *h;
+
+ if (fread (&m, sizeof (m), 1, f) != 1)
+ goto error;
+
+ if (m.name_length == 0)
+ break;
+
+ if (defnlen < m.definition_length + 1)
+ {
+ defnlen = m.definition_length + 256;
+ defn = xrealloc (defn, defnlen);
+ }
+
+ if (fread (defn, 1, m.definition_length, f) != m.definition_length)
+ goto error;
+ defn[m.definition_length] = '\0';
+
+ h = cpp_lookup (r, defn, m.name_length);
+
+ if (h->type == NT_MACRO)
+ _cpp_free_definition (h);
+ if (m.flags & NODE_POISONED)
+ h->flags |= NODE_POISONED | NODE_DIAGNOSTIC;
+ else if (m.name_length != m.definition_length)
+ {
+ if (cpp_push_buffer (r, defn + m.name_length,
+ m.definition_length - m.name_length,
+ true, 1) != NULL)
+ {
+ if (!_cpp_create_definition (r, h))
+ abort ();
+ _cpp_pop_buffer (r);
+ }
+ else
+ abort ();
+ }
+ }
+
+ r->state = old_state;
+ r->line = saved_line;
+ free (defn);
+ defn = NULL;
+
+ if (deps_restore (r->deps, f, CPP_OPTION (r, restore_pch_deps) ? name : NULL)
+ != 0)
+ goto error;
+
+ return 0;
+
+ error:
+ cpp_errno (r, DL_ERROR, "while reading precompiled header");
+ return -1;
+}
diff --git a/gcc/dbxout.c b/gcc/dbxout.c
index 5fcd28d8fc1..480ef821b70 100644
--- a/gcc/dbxout.c
+++ b/gcc/dbxout.c
@@ -137,57 +137,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#define STABS_GCC_MARKER "gcc2_compiled."
#endif
-/* Typical USG systems don't have stab.h, and they also have
- no use for DBX-format debugging info. */
-
-#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
-
-/* Nonzero if we have actually used any of the GDB extensions
- to the debugging format. The idea is that we use them for the
- first time only if there's a strong reason, but once we have done that,
- we use them whenever convenient. */
-
-static int have_used_extensions = 0;
-
-/* Number for the next N_SOL filename stabs label. The number 0 is reserved
- for the N_SO filename stabs label. */
-
-#if defined (DBX_DEBUGGING_INFO) && !defined (DBX_OUTPUT_SOURCE_FILENAME)
-static int source_label_number = 1;
-#endif
-
-#ifdef DEBUG_SYMS_TEXT
-#define FORCE_TEXT function_section (current_function_decl);
-#else
-#define FORCE_TEXT
-#endif
-
-#include "gstab.h"
-
-#define STAB_CODE_TYPE enum __stab_debug_code
-
-/* 1 if PARM is passed to this function in memory. */
-
-#define PARM_PASSED_IN_MEMORY(PARM) \
- (GET_CODE (DECL_INCOMING_RTL (PARM)) == MEM)
-
-/* A C expression for the integer offset value of an automatic variable
- (N_LSYM) having address X (an RTX). */
-#ifndef DEBUGGER_AUTO_OFFSET
-#define DEBUGGER_AUTO_OFFSET(X) \
- (GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0)
-#endif
-
-/* A C expression for the integer offset value of an argument (N_PSYM)
- having address X (an RTX). The nominal offset is OFFSET. */
-#ifndef DEBUGGER_ARG_OFFSET
-#define DEBUGGER_ARG_OFFSET(OFFSET, X) (OFFSET)
-#endif
-
-/* Stream for writing to assembler file. */
-
-static FILE *asmfile;
-
/* Last source file name mentioned in a NOTE insn. */
static const char *lastfile;
@@ -205,13 +154,11 @@ enum typestatus {TYPE_UNSEEN, TYPE_XREF, TYPE_DEFINED};
The file_number and type_number elements are used if DBX_USE_BINCL
is defined. */
-struct typeinfo
+struct typeinfo GTY(())
{
enum typestatus status;
-#ifdef DBX_USE_BINCL
int file_number;
int type_number;
-#endif
};
/* Vector recording information about C data types.
@@ -219,25 +166,23 @@ struct typeinfo
we assign it a number using next_type_number.
That is its index in this vector. */
-struct typeinfo *typevec;
+static GTY ((length ("typevec_len"))) struct typeinfo *typevec;
/* Number of elements of space allocated in `typevec'. */
-static int typevec_len;
+static GTY(()) int typevec_len;
/* In dbx output, each type gets a unique number.
This is the number for the next type output.
The number, once assigned, is in the TYPE_SYMTAB_ADDRESS field. */
-static int next_type_number;
-
-#ifdef DBX_USE_BINCL
+static GTY(()) int next_type_number;
/* When using N_BINCL in dbx output, each type number is actually a
pair of the file number and the type number within the file.
This is a stack of input files. */
-struct dbx_file
+struct dbx_file GTY(())
{
struct dbx_file *next;
int file_number;
@@ -246,13 +191,62 @@ struct dbx_file
/* This is the top of the stack. */
-static struct dbx_file *current_file;
+static GTY(()) struct dbx_file *current_file;
/* This is the next file number to use. */
-static int next_file_number;
+static GTY(()) int next_file_number;
+
+/* Typical USG systems don't have stab.h, and they also have
+ no use for DBX-format debugging info. */
+
+#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
+
+/* Nonzero if we have actually used any of the GDB extensions
+ to the debugging format. The idea is that we use them for the
+ first time only if there's a strong reason, but once we have done that,
+ we use them whenever convenient. */
+
+static int have_used_extensions = 0;
+
+/* Number for the next N_SOL filename stabs label. The number 0 is reserved
+ for the N_SO filename stabs label. */
+
+#if defined (DBX_DEBUGGING_INFO) && !defined (DBX_OUTPUT_SOURCE_FILENAME)
+static int source_label_number = 1;
+#endif
+
+#ifdef DEBUG_SYMS_TEXT
+#define FORCE_TEXT function_section (current_function_decl);
+#else
+#define FORCE_TEXT
+#endif
+
+#include "gstab.h"
+
+#define STAB_CODE_TYPE enum __stab_debug_code
+
+/* 1 if PARM is passed to this function in memory. */
+
+#define PARM_PASSED_IN_MEMORY(PARM) \
+ (GET_CODE (DECL_INCOMING_RTL (PARM)) == MEM)
-#endif /* DBX_USE_BINCL */
+/* A C expression for the integer offset value of an automatic variable
+ (N_LSYM) having address X (an RTX). */
+#ifndef DEBUGGER_AUTO_OFFSET
+#define DEBUGGER_AUTO_OFFSET(X) \
+ (GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0)
+#endif
+
+/* A C expression for the integer offset value of an argument (N_PSYM)
+ having address X (an RTX). The nominal offset is OFFSET. */
+#ifndef DEBUGGER_ARG_OFFSET
+#define DEBUGGER_ARG_OFFSET(OFFSET, X) (OFFSET)
+#endif
+
+/* Stream for writing to assembler file. */
+
+static FILE *asmfile;
/* These variables are for dbxout_symbol to communicate to
dbxout_finish_symbol.
@@ -425,7 +419,7 @@ dbxout_init (input_file_name)
asmfile = asm_out_file;
typevec_len = 100;
- typevec = (struct typeinfo *) xcalloc (typevec_len, sizeof typevec[0]);
+ typevec = (struct typeinfo *) ggc_calloc (typevec_len, sizeof typevec[0]);
/* Convert Ltext into the appropriate format for local labels in case
the system doesn't insert underscores in front of user generated
@@ -484,7 +478,7 @@ dbxout_init (input_file_name)
next_type_number = 1;
#ifdef DBX_USE_BINCL
- current_file = (struct dbx_file *) xmalloc (sizeof *current_file);
+ current_file = (struct dbx_file *) ggc_alloc (sizeof *current_file);
current_file->next = NULL;
current_file->file_number = 0;
current_file->next_type_number = 1;
@@ -541,7 +535,7 @@ dbxout_start_source_file (line, filename)
const char *filename ATTRIBUTE_UNUSED;
{
#ifdef DBX_USE_BINCL
- struct dbx_file *n = (struct dbx_file *) xmalloc (sizeof *n);
+ struct dbx_file *n = (struct dbx_file *) ggc_alloc (sizeof *n);
n->next = current_file;
n->file_number = next_file_number++;
@@ -560,12 +554,8 @@ dbxout_end_source_file (line)
unsigned int line ATTRIBUTE_UNUSED;
{
#ifdef DBX_USE_BINCL
- struct dbx_file *next;
-
fprintf (asmfile, "%s%d,0,0,0\n", ASM_STABN_OP, N_EINCL);
- next = current_file->next;
- free (current_file);
- current_file = next;
+ current_file = current_file->next;
#endif
}
@@ -1149,8 +1139,9 @@ dbxout_type (type, full)
if (next_type_number == typevec_len)
{
typevec
- = (struct typeinfo *) xrealloc (typevec,
- typevec_len * 2 * sizeof typevec[0]);
+ = (struct typeinfo *) ggc_realloc (typevec,
+ (typevec_len * 2
+ * sizeof typevec[0]));
memset ((char *) (typevec + typevec_len), 0,
typevec_len * sizeof typevec[0]);
typevec_len *= 2;
@@ -3008,3 +2999,5 @@ dbxout_begin_function (decl)
#endif /* DBX_DEBUGGING_INFO */
#endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */
+
+#include "gt-dbxout.h"
diff --git a/gcc/doc/cppopts.texi b/gcc/doc/cppopts.texi
index 74fe8be5b7d..95311a86d4e 100644
--- a/gcc/doc/cppopts.texi
+++ b/gcc/doc/cppopts.texi
@@ -301,6 +301,17 @@ a dependency output file as a side-effect of the compilation process.
Like @option{-MD} except mention only user header files, not system
-header files.
+@ifclear cppmanual
+@item -fpch-deps
+@opindex fpch-deps
+When using precompiled headers (@pxref{Precompiled Headers}), this flag
+will cause the dependency-output flags to also list the files from the
+precompiled header's dependencies. If not specified only the
+precompiled header would be listed and not the files that were used to
+create it because those files are not consulted when a precompiled
+header is used.
+
+@end ifclear
@item -x c
@itemx -x c++
@itemx -x objective-c
diff --git a/gcc/doc/gty.texi b/gcc/doc/gty.texi
index 55deef24f69..ed7d3d2c1a1 100644
--- a/gcc/doc/gty.texi
+++ b/gcc/doc/gty.texi
@@ -10,7 +10,8 @@
GCC uses some fairly sophisticated memory management techniques, which
involve determining information about GCC's data structures from GCC's
-source code and using this information to perform garbage collection.
+source code and using this information to perform garbage collection and
+implement precompiled headers.
A full C parser would be too overcomplicated for this task, so a limited
subset of C is interpreted and special markers are used to determine
@@ -227,6 +228,39 @@ this field is always @code{NULL}. This is used to avoid requiring
backends to define certain optional structures. It doesn't work with
language frontends.
+@findex chain_next
+@findex chain_prev
+@item chain_next
+@itemx chain_prev
+
+It's helpful for the type machinery to know if objects are often
+chained together in long lists; this lets it generate code that uses
+less stack space by iterating along the list instead of recursing down
+it. @code{chain_next} is an expression for the next item in the list,
+@code{chain_prev} is an expression for the previous item. The
+machinery requires that taking the next item of the previous item
+gives the original item.
+
+@findex reorder
+@item reorder
+
+Some data structures depend on the relative ordering of pointers. If
+the type machinery needs to change that ordering, it will call the
+function referenced by the @code{reorder} option, before changing the
+pointers in the object that's pointed to by the field the option
+applies to. The function must be of the type @code{void ()(void *,
+void *, gt_pointer_operator, void *)}. The second parameter is the
+pointed-to object; the third parameter is a routine that, given a
+pointer, can update it to its new value. The fourth parameter is a
+cookie to be passed to the third parameter. The first parameter is
+the structure that contains the object, or the object itself if it is
+a structure.
+
+No data structure may depend on the absolute value of pointers. Even
+relying on relative orderings and using @code{reorder} functions can
+be expensive. It is better to depend on properties of the data, like
+an ID number or the hash of a string instead.
+
@findex special
@item special
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 8b3e365a550..bfbdd3ebbc2 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -141,6 +141,7 @@ only one of these two forms, whichever one is not the default.
* Code Gen Options:: Specifying conventions for function calls, data layout
and register usage.
* Environment Variables:: Env vars that affect GCC.
+* Precompiled Headers:: Compiling a header once, and using it many times.
* Running Protoize:: Automatically adding or removing function prototypes.
@end menu
@@ -220,7 +221,7 @@ in the following sections.
-Wimplicit -Wimplicit-int @gol
-Wimplicit-function-declaration @gol
-Werror-implicit-function-declaration @gol
--Wimport -Winline -Wno-endif-labels @gol
+-Wimport -Winline -Winvalid-pch -Wno-endif-labels @gol
-Wlarger-than-@var{len} -Wlong-long @gol
-Wmain -Wmissing-braces @gol
-Wmissing-format-attribute -Wmissing-noreturn @gol
@@ -767,7 +768,7 @@ Objective-C source code. Note that you must link with the library
Objective-C source code which should not be preprocessed.
@item @var{file}.h
-C header file (not to be compiled or linked).
+C or C++ header file to be turned into a precompiled header.
@item @var{file}.cc
@itemx @var{file}.cp
@@ -780,6 +781,10 @@ C++ source code which must be preprocessed. Note that in @samp{.cxx},
the last two letters must both be literally @samp{x}. Likewise,
@samp{.C} refers to a literal capital C@.
+@item @var{file}.hh
+@itemx @var{file}.H
+C++ header file to be turned into a precompiled header.
+
@item @var{file}.f
@itemx @var{file}.for
@itemx @var{file}.FOR
@@ -843,7 +848,7 @@ name suffix). This option applies to all following input files until
the next @option{-x} option. Possible values for @var{language} are:
@example
c c-header cpp-output
-c++ c++-cpp-output
+c++ c++-header c++-cpp-output
objective-c objc-cpp-output
assembler assembler-with-cpp
ada
@@ -965,22 +970,24 @@ Display the version number and copyrights of the invoked GCC.
@cindex suffixes for C++ source
@cindex C++ source file suffixes
C++ source files conventionally use one of the suffixes @samp{.C},
-@samp{.cc}, @samp{.cpp}, @samp{.CPP}, @samp{.c++}, @samp{.cp}, or @samp{.cxx};
+@samp{.cc}, @samp{.cpp}, @samp{.CPP}, @samp{.c++}, @samp{.cp}, or
+@samp{.cxx}; C++ header files often use @samp{.hh} or @samp{.H}; and
preprocessed C++ files use the suffix @samp{.ii}. GCC recognizes
files with these names and compiles them as C++ programs even if you
-call the compiler the same way as for compiling C programs (usually with
-the name @command{gcc}).
+call the compiler the same way as for compiling C programs (usually
+with the name @command{gcc}).
@findex g++
@findex c++
However, C++ programs often require class libraries as well as a
compiler that understands the C++ language---and under some
-circumstances, you might want to compile programs from standard input,
-or otherwise without a suffix that flags them as C++ programs.
-@command{g++} is a program that calls GCC with the default language
-set to C++, and automatically specifies linking against the C++
-library. On many systems, @command{g++} is also
-installed with the name @command{c++}.
+circumstances, you might want to compile programs or header files from
+standard input, or otherwise without a suffix that flags them as C++
+programs. You might also like to precompile a C header file with a
+@samp{.h} extension to be used in C++ compilations. @command{g++} is a
+program that calls GCC with the default language set to C++, and
+automatically specifies linking against the C++ library. On many
+systems, @command{g++} is also installed with the name @command{c++}.
@cindex invoking @command{g++}
When you compile C++ programs, you may specify many of the same
@@ -2800,6 +2807,11 @@ code is to provide behavior which is selectable at compile-time.
@opindex Winline
Warn if a function can not be inlined and it was declared as inline.
+@item -Winvalid-pch
+@opindex Winvalid-pch
+Warn if a precompiled header (@pxref{Precompiled Headers}) is found in
+the search path but can't be used.
+
@item -Wlong-long
@opindex Wlong-long
@opindex Wno-long-long
@@ -10924,6 +10936,104 @@ preprocessor.
@c man end
+@node Precompiled Headers
+@section Using Precompiled Headers
+@cindex precompiled headers
+@cindex speed of compilation
+
+Often large projects have many header files that are included in every
+source file. The time the compiler takes to process these header files
+over and over again can account for nearly all of the time required to
+build the project. To make builds faster, GCC allows users to
+`precompile' a header file; then, if builds can use the precompiled
+header file they will be much faster.
+
+To create a precompiled header file, simply compile it as you would any
+other file, if necessary using the @option{-x} option to make the driver
+treat it as a C or C++ header file. You will probably want to use a
+tool like @command{make} to keep the precompiled header up-to-date when
+the headers it contains change.
+
+A precompiled header file will be searched for when @code{#include} is
+seen in the compilation. As it searches for the included file
+(@pxref{Search Path,,Search Path,cpp.info,The C Preprocessor}) the
+compiler looks for a precompiled header in each directory just before it
+looks for the include file in that directory. The name searched for is
+the name specified in the @code{#include} with @samp{.pch} appended. If
+the precompiled header file can't be used, it is ignored.
+
+For instance, if you have @code{#include "all.h"}, and you have
+@file{all.h.pch} in the same directory as @file{all.h}, then the
+precompiled header file will be used if possible, and the original
+header will be used otherwise.
+
+Alternatively, you might decide to put the precompiled header file in a
+directory and use @option{-I} to ensure that directory is searched
+before (or instead of) the directory containing the original header.
+Then, if you want to check that the precompiled header file is always
+used, you can put a file of the same name as the original header in this
+directory containing an @code{#error} command.
+
+This also works with @option{-include}. So yet another way to use
+precompiled headers, good for projects not designed with precompiled
+header files in mind, is to simply take most of the header files used by
+a project, include them from another header file, precompile that header
+file, and @option{-include} the precompiled header. If the header files
+have guards against multiple inclusion, they will be skipped because
+they've already been included (in the precompiled header).
+
+If you need to precompile the same header file for different
+languages, targets, or compiler options, you can instead make a
+@emph{directory} named like @file{all.h.pch}, and put each precompiled
+header in the directory. (It doesn't matter what you call the files
+in the directory, every precompiled header in the directory will be
+considered.) The first precompiled header encountered in the
+directory that is valid for this compilation will be used; they're
+searched in no particular order.
+
+There are many other possibilities, limited only by your imagination,
+good sense, and the constraints of your build system.
+
+A precompiled header file can be used only when these conditions apply:
+
+@itemize
+@item
+Only one precompiled header can be used in a particular compilation.
+@item
+A precompiled header can't be used once the first C token is seen. You
+can have preprocessor directives before a precompiled header; you can
+even include a precompiled header from inside another header, so long as
+there are no C tokens before the @code{#include}.
+@item
+The precompiled header file must be produced for the same language as
+the current compilation. You can't use a C precompiled header for a C++
+compilation.
+@item
+The precompiled header file must be produced by the same compiler
+version and configuration as the current compilation is using.
+The easiest way to guarantee this is to use the same compiler binary
+for creating and using precompiled headers.
+@item
+Any macros defined before the precompiled header (including with
+@option{-D}) must either be defined in the same way as when the
+precompiled header was generated, or must not affect the precompiled
+header, which usually means that the they don't appear in the
+precompiled header at all.
+@item
+Certain command-line options must be defined in the same way as when the
+precompiled header was generated. At present, it's not clear which
+options are safe to change and which are not; the safest choice is to
+use exactly the same options when generating and using the precompiled
+header.
+@end itemize
+
+For all of these but the last, the compiler will automatically ignore
+the precompiled header if the conditions aren't met. For the last item,
+some option changes will cause the precompiled header to be rejected,
+but not all incompatible option combinations have yet been found. If
+you find a new incompatible combination, please consider filing a bug
+report, see @ref{Bugs}.
+
@node Running Protoize
@section Running Protoize
diff --git a/gcc/doc/passes.texi b/gcc/doc/passes.texi
index c47433eccfc..8a96a692461 100644
--- a/gcc/doc/passes.texi
+++ b/gcc/doc/passes.texi
@@ -1,4 +1,4 @@
-@c Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+@c Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2002,
@c 1999, 2000, 2001 Free Software Foundation, Inc.
@c This is part of the GCC manual.
@c For copying conditions, see the file gcc.texi.
@@ -73,54 +73,22 @@ performed by cpplib, which is covered in separate documentation. In
particular, the internals are covered in @xref{Top, ,Cpplib internals,
cppinternals, Cpplib Internals}.
-@c Avoiding overfull is tricky here.
-The source files to parse C are
-@file{c-convert.c},
-@file{c-decl.c},
-@file{c-errors.c},
-@file{c-lang.c},
-@file{c-objc-common.c},
-@file{c-parse.in},
-@file{c-aux-info.c},
-and
-@file{c-typeck.c},
-along with a header file
-@file{c-tree.h}
-and some files shared with Objective-C and C++.
-
-The source files for parsing C++ are in @file{cp/}.
-They are @file{parse.y},
-@file{class.c},
-@file{cvt.c}, @file{decl.c}, @file{decl2.c},
-@file{except.c},
-@file{expr.c}, @file{init.c}, @file{lex.c},
-@file{method.c}, @file{ptree.c},
-@file{search.c}, @file{spew.c},
-@file{semantics.c}, @file{tree.c},
-@file{typeck2.c}, and
-@file{typeck.c}, along with header files @file{cp-tree.def},
-@file{cp-tree.h}, and @file{decl.h}.
-
-The special source files for parsing Objective-C are in @file{objc/}.
-They are @file{objc-act.c}, @file{objc-tree.def}, and @file{objc-act.h}.
-Certain C-specific files are used for this as well.
-
-The files
-@file{c-common.c},
+The source files to parse C are found in the toplevel directory, and
+by convention are named @file{c-*}. Some of these are also used by
+the other C-like languages: @file{c-common.c},
@file{c-common.def},
@file{c-format.c},
@file{c-opts.c},
@file{c-pragma.c},
@file{c-semantics.c},
-and
@file{c-lex.c},
-along with header files
@file{c-common.h},
@file{c-dump.h},
and
@file{c-pragma.h},
-are also used for all of the above languages.
+Files specific to each language are in subdirectories named after the
+language in question, like @file{ada}, @file{objc}, @file{cp} (for C++).
@cindex Tree optimization
@item
diff --git a/gcc/dwarf2asm.c b/gcc/dwarf2asm.c
index 777ba8da71c..396c2cdd355 100644
--- a/gcc/dwarf2asm.c
+++ b/gcc/dwarf2asm.c
@@ -688,12 +688,12 @@ dw2_asm_output_delta_sleb128 VPARAMS ((const char *lab1 ATTRIBUTE_UNUSED,
VA_CLOSE (ap);
}
-static int mark_indirect_pool_entry PARAMS ((splay_tree_node, void *));
-static void mark_indirect_pool PARAMS ((PTR arg));
static rtx dw2_force_const_mem PARAMS ((rtx));
static int dw2_output_indirect_constant_1 PARAMS ((splay_tree_node, void *));
-static splay_tree indirect_pool;
+static GTY((param1_is (char *), param2_is (tree))) splay_tree indirect_pool;
+
+static GTY(()) int dw2_const_labelno;
#if defined(HAVE_GAS_HIDDEN) && defined(SUPPORTS_ONE_ONLY)
# define USE_LINKONCE_INDIRECT 1
@@ -701,26 +701,6 @@ static splay_tree indirect_pool;
# define USE_LINKONCE_INDIRECT 0
#endif
-/* Mark all indirect constants for GC. */
-
-static int
-mark_indirect_pool_entry (node, data)
- splay_tree_node node;
- void* data ATTRIBUTE_UNUSED;
-{
- ggc_mark_tree ((tree) node->value);
- return 0;
-}
-
-/* Mark all indirect constants for GC. */
-
-static void
-mark_indirect_pool (arg)
- PTR arg ATTRIBUTE_UNUSED;
-{
- splay_tree_foreach (indirect_pool, mark_indirect_pool_entry, NULL);
-}
-
/* Put X, a SYMBOL_REF, in memory. Return a SYMBOL_REF to the allocated
memory. Differs from force_const_mem in that a single pool is used for
the entire unit of translation, and the memory is not guaranteed to be
@@ -735,10 +715,7 @@ dw2_force_const_mem (x)
tree decl;
if (! indirect_pool)
- {
- indirect_pool = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
- ggc_add_root (&indirect_pool, 1, sizeof indirect_pool, mark_indirect_pool);
- }
+ indirect_pool = splay_tree_new_ggc (splay_tree_compare_pointers);
if (GET_CODE (x) != SYMBOL_REF)
abort ();
@@ -765,11 +742,10 @@ dw2_force_const_mem (x)
}
else
{
- extern int const_labelno;
char label[32];
- ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno);
- ++const_labelno;
+ ASM_GENERATE_INTERNAL_LABEL (label, "LDFCM", dw2_const_labelno);
+ ++dw2_const_labelno;
id = get_identifier (label);
decl = build_decl (VAR_DECL, id, ptr_type_node);
DECL_ARTIFICIAL (decl) = 1;
@@ -906,3 +882,5 @@ dw2_asm_output_encoded_addr_rtx VPARAMS ((int encoding,
VA_CLOSE (ap);
}
+
+#include "gt-dwarf2asm.h"
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index c93142069b3..38d34002533 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -63,7 +63,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "debug.h"
#include "target.h"
#include "langhooks.h"
-#include "hashtable.h"
#include "hashtab.h"
#ifdef DWARF2_DEBUGGING_INFO
@@ -163,8 +162,6 @@ static GTY(()) varray_type incomplete_types;
define type declaration DIE's. */
static GTY(()) varray_type decl_scope_table;
-#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
-
/* How to start an assembler comment. */
#ifndef ASM_COMMENT_START
#define ASM_COMMENT_START ";#"
@@ -179,21 +176,31 @@ typedef union dw_cfi_oprnd_struct *dw_cfi_oprnd_ref;
and address fields are provided as possible operands;
their use is selected by the opcode field. */
-typedef union dw_cfi_oprnd_struct
+enum dw_cfi_oprnd_type {
+ dw_cfi_oprnd_unused,
+ dw_cfi_oprnd_reg_num,
+ dw_cfi_oprnd_offset,
+ dw_cfi_oprnd_addr,
+ dw_cfi_oprnd_loc
+};
+
+typedef union dw_cfi_oprnd_struct GTY(())
{
- unsigned long dw_cfi_reg_num;
- long int dw_cfi_offset;
- const char *dw_cfi_addr;
- struct dw_loc_descr_struct *dw_cfi_loc;
+ unsigned long GTY ((tag ("dw_cfi_oprnd_reg_num"))) dw_cfi_reg_num;
+ long int GTY ((tag ("dw_cfi_oprnd_offset"))) dw_cfi_offset;
+ const char * GTY ((tag ("dw_cfi_oprnd_addr"))) dw_cfi_addr;
+ struct dw_loc_descr_struct * GTY ((tag ("dw_cfi_oprnd_loc"))) dw_cfi_loc;
}
dw_cfi_oprnd;
-typedef struct dw_cfi_struct
+typedef struct dw_cfi_struct GTY(())
{
dw_cfi_ref dw_cfi_next;
enum dwarf_call_frame_info dw_cfi_opc;
- dw_cfi_oprnd dw_cfi_oprnd1;
- dw_cfi_oprnd dw_cfi_oprnd2;
+ dw_cfi_oprnd GTY ((desc ("dw_cfi_oprnd1_desc (%1.dw_cfi_opc)")))
+ dw_cfi_oprnd1;
+ dw_cfi_oprnd GTY ((desc ("dw_cfi_oprnd2_desc (%1.dw_cfi_opc)")))
+ dw_cfi_oprnd2;
}
dw_cfi_node;
@@ -202,7 +209,7 @@ dw_cfi_node;
It can now be either REG + CFA_OFFSET or *(REG + BASE_OFFSET) + CFA_OFFSET.
Instead of passing around REG and OFFSET, we pass a copy
of this structure. */
-typedef struct cfa_loc
+typedef struct cfa_loc GTY(())
{
unsigned long reg;
long offset;
@@ -216,7 +223,7 @@ typedef struct cfa_loc
CIE obviates the need to keep track of multiple CIE's
in the DWARF generation routines below. */
-typedef struct dw_fde_struct
+typedef struct dw_fde_struct GTY(())
{
const char *dw_fde_begin;
const char *dw_fde_current_label;
@@ -267,7 +274,7 @@ dw_fde_node;
/* A pointer to the base of a table that contains frame description
information for each routine. */
-static dw_fde_ref fde_table;
+static GTY((length ("fde_table_allocated"))) dw_fde_ref fde_table;
/* Number of elements currently allocated for fde_table. */
static unsigned fde_table_allocated;
@@ -280,7 +287,7 @@ static unsigned fde_table_in_use;
#define FDE_TABLE_INCREMENT 256
/* A list of call frame insns for the CIE. */
-static dw_cfi_ref cie_cfi_head;
+static GTY(()) dw_cfi_ref cie_cfi_head;
/* Some DWARF extensions (e.g., MIPS/SGI) implement a subprogram
attribute that accelerates the lookup of the FDE associated
@@ -288,16 +295,20 @@ static dw_cfi_ref cie_cfi_head;
associated with the current function (body) definition. */
static unsigned current_funcdef_fde;
-struct ht *debug_str_hash;
-
-struct indirect_string_node
+struct indirect_string_node GTY(())
{
- struct ht_identifier id;
+ const char *str;
unsigned int refcount;
unsigned int form;
char *label;
};
+static GTY ((param_is (struct indirect_string_node))) htab_t debug_str_hash;
+
+static GTY(()) int dw2_string_counter;
+
+#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
+
/* Forward declarations for functions defined in this file. */
static char *stripattributes PARAMS ((const char *));
@@ -313,6 +324,10 @@ static void reg_save PARAMS ((const char *, unsigned,
static void initial_return_save PARAMS ((rtx));
static long stack_adjust_offset PARAMS ((rtx));
static void output_cfi PARAMS ((dw_cfi_ref, dw_fde_ref, int));
+static enum dw_cfi_oprnd_type dw_cfi_oprnd1_desc
+ PARAMS ((enum dwarf_call_frame_info cfi));
+static enum dw_cfi_oprnd_type dw_cfi_oprnd2_desc
+ PARAMS ((enum dwarf_call_frame_info cfi));
static void output_call_frame_info PARAMS ((int));
static void dwarf2out_stack_adjust PARAMS ((rtx));
static void queue_reg_save PARAMS ((const char *, rtx, long));
@@ -515,7 +530,7 @@ dwarf_cfi_name (cfi_opc)
static inline dw_cfi_ref
new_cfi ()
{
- dw_cfi_ref cfi = (dw_cfi_ref) xmalloc (sizeof (dw_cfi_node));
+ dw_cfi_ref cfi = (dw_cfi_ref) ggc_alloc (sizeof (dw_cfi_node));
cfi->dw_cfi_next = NULL;
cfi->dw_cfi_oprnd1.dw_cfi_reg_num = 0;
@@ -1086,18 +1101,22 @@ dwarf2out_stack_adjust (insn)
dwarf2out_args_size (label, args_size);
}
+#endif
+
/* We delay emitting a register save until either (a) we reach the end
of the prologue or (b) the register is clobbered. This clusters
register saves so that there are fewer pc advances. */
-struct queued_reg_save
+struct queued_reg_save GTY(())
{
struct queued_reg_save *next;
rtx reg;
long cfa_offset;
};
-static struct queued_reg_save *queued_reg_saves;
+static GTY(()) struct queued_reg_save *queued_reg_saves;
+
+#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
static const char *last_reg_save_label;
static void
@@ -1106,7 +1125,7 @@ queue_reg_save (label, reg, offset)
rtx reg;
long offset;
{
- struct queued_reg_save *q = (struct queued_reg_save *) xmalloc (sizeof (*q));
+ struct queued_reg_save *q = ggc_alloc (sizeof (*q));
q->next = queued_reg_saves;
q->reg = reg;
@@ -1125,7 +1144,6 @@ flush_queued_reg_saves ()
{
dwarf2out_reg_save (last_reg_save_label, REGNO (q->reg), q->cfa_offset);
next = q->next;
- free (q);
}
queued_reg_saves = NULL;
@@ -1678,6 +1696,78 @@ dwarf2out_frame_debug (insn)
dwarf2out_frame_debug_expr (insn, label);
}
+#endif
+
+/* Describe for the GTY machinery what parts of dw_cfi_oprnd1 are used. */
+
+static enum dw_cfi_oprnd_type
+dw_cfi_oprnd1_desc (cfi)
+ enum dwarf_call_frame_info cfi;
+{
+ switch (cfi)
+ {
+ case DW_CFA_nop:
+ case DW_CFA_GNU_window_save:
+ return dw_cfi_oprnd_unused;
+
+ case DW_CFA_set_loc:
+ case DW_CFA_advance_loc1:
+ case DW_CFA_advance_loc2:
+ case DW_CFA_advance_loc4:
+ case DW_CFA_MIPS_advance_loc8:
+ return dw_cfi_oprnd_addr;
+
+ case DW_CFA_offset:
+ case DW_CFA_offset_extended:
+ case DW_CFA_def_cfa:
+ case DW_CFA_offset_extended_sf:
+ case DW_CFA_def_cfa_sf:
+ case DW_CFA_restore_extended:
+ case DW_CFA_undefined:
+ case DW_CFA_same_value:
+ case DW_CFA_def_cfa_register:
+ case DW_CFA_register:
+ return dw_cfi_oprnd_reg_num;
+
+ case DW_CFA_def_cfa_offset:
+ case DW_CFA_GNU_args_size:
+ case DW_CFA_def_cfa_offset_sf:
+ return dw_cfi_oprnd_offset;
+
+ case DW_CFA_def_cfa_expression:
+ case DW_CFA_expression:
+ return dw_cfi_oprnd_loc;
+
+ default:
+ abort ();
+ }
+}
+
+/* Describe for the GTY machinery what parts of dw_cfi_oprnd2 are used. */
+
+static enum dw_cfi_oprnd_type
+dw_cfi_oprnd2_desc (cfi)
+ enum dwarf_call_frame_info cfi;
+{
+ switch (cfi)
+ {
+ case DW_CFA_def_cfa:
+ case DW_CFA_def_cfa_sf:
+ case DW_CFA_offset:
+ case DW_CFA_offset_extended_sf:
+ case DW_CFA_offset_extended:
+ return dw_cfi_oprnd_offset;
+
+ case DW_CFA_register:
+ return dw_cfi_oprnd_reg_num;
+
+ default:
+ return dw_cfi_oprnd_unused;
+ }
+}
+
+#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
+
/* Output a Call Frame Information opcode and its operand(s). */
static void
@@ -2118,9 +2208,10 @@ dwarf2out_begin_prologue (line, file)
if (fde_table_in_use == fde_table_allocated)
{
fde_table_allocated += FDE_TABLE_INCREMENT;
- fde_table
- = (dw_fde_ref) xrealloc (fde_table,
- fde_table_allocated * sizeof (dw_fde_node));
+ fde_table = ggc_realloc (fde_table,
+ fde_table_allocated * sizeof (dw_fde_node));
+ memset (fde_table + fde_table_in_use, 0,
+ FDE_TABLE_INCREMENT * sizeof (dw_fde_node));
}
/* Record the FDE associated with this function. */
@@ -2172,7 +2263,8 @@ void
dwarf2out_frame_init ()
{
/* Allocate the initial hunk of the fde_table. */
- fde_table = (dw_fde_ref) xcalloc (FDE_TABLE_INCREMENT, sizeof (dw_fde_node));
+ fde_table = (dw_fde_ref) ggc_alloc_cleared (FDE_TABLE_INCREMENT
+ * sizeof (dw_fde_node));
fde_table_allocated = FDE_TABLE_INCREMENT;
fde_table_in_use = 0;
@@ -2196,6 +2288,7 @@ dwarf2out_frame_finish ()
if (! USING_SJLJ_EXCEPTIONS && (flag_unwind_tables || flag_exceptions))
output_call_frame_info (1);
}
+#endif
/* And now, the subset of the debugging information support code necessary
for emitting location expressions. */
@@ -2214,7 +2307,7 @@ typedef struct dw_loc_list_struct *dw_loc_list_ref;
can take on several forms. The forms that are used in this
implementation are listed below. */
-typedef enum
+enum dw_val_class
{
dw_val_class_addr,
dw_val_class_offset,
@@ -2231,13 +2324,12 @@ typedef enum
dw_val_class_lbl_id,
dw_val_class_lbl_offset,
dw_val_class_str
-}
-dw_val_class;
+};
/* Describe a double word constant value. */
/* ??? Every instance of long_long in the code really means CONST_DOUBLE. */
-typedef struct dw_long_long_struct
+typedef struct dw_long_long_struct GTY(())
{
unsigned long hi;
unsigned long low;
@@ -2246,9 +2338,9 @@ dw_long_long_const;
/* Describe a floating point constant value. */
-typedef struct dw_fp_struct
+typedef struct dw_fp_struct GTY(())
{
- long *array;
+ long * GTY((length ("%h.length"))) array;
unsigned length;
}
dw_float_const;
@@ -2256,37 +2348,37 @@ dw_float_const;
/* The dw_val_node describes an attribute's value, as it is
represented internally. */
-typedef struct dw_val_struct
+typedef struct dw_val_struct GTY(())
{
- dw_val_class val_class;
- union
+ enum dw_val_class val_class;
+ union dw_val_struct_union
{
- rtx val_addr;
- long unsigned val_offset;
- dw_loc_list_ref val_loc_list;
- dw_loc_descr_ref val_loc;
- long int val_int;
- long unsigned val_unsigned;
- dw_long_long_const val_long_long;
- dw_float_const val_float;
- struct
+ rtx GTY ((tag ("dw_val_class_addr"))) val_addr;
+ long unsigned GTY ((tag ("dw_val_class_offset"))) val_offset;
+ dw_loc_list_ref GTY ((tag ("dw_val_class_loc_list"))) val_loc_list;
+ dw_loc_descr_ref GTY ((tag ("dw_val_class_loc"))) val_loc;
+ long int GTY ((default (""))) val_int;
+ long unsigned GTY ((tag ("dw_val_class_unsigned_const"))) val_unsigned;
+ dw_long_long_const GTY ((tag ("dw_val_class_long_long"))) val_long_long;
+ dw_float_const GTY ((tag ("dw_val_class_float"))) val_float;
+ struct dw_val_die_union
{
dw_die_ref die;
int external;
- } val_die_ref;
- unsigned val_fde_index;
- struct indirect_string_node *val_str;
- char *val_lbl_id;
- unsigned char val_flag;
+ } GTY ((tag ("dw_val_class_die_ref"))) val_die_ref;
+ unsigned GTY ((tag ("dw_val_class_fde_ref"))) val_fde_index;
+ struct indirect_string_node * GTY ((tag ("dw_val_class_str"))) val_str;
+ char * GTY ((tag ("dw_val_class_lbl_id"))) val_lbl_id;
+ unsigned char GTY ((tag ("dw_val_class_flag"))) val_flag;
}
- v;
+ GTY ((desc ("%1.val_class"))) v;
}
dw_val_node;
/* Locations in memory are described using a sequence of stack machine
operations. */
-typedef struct dw_loc_descr_struct
+typedef struct dw_loc_descr_struct GTY(())
{
dw_loc_descr_ref dw_loc_next;
enum dwarf_location_atom dw_loc_opc;
@@ -2299,7 +2391,7 @@ dw_loc_descr_node;
/* Location lists are ranges + location descriptions for that range,
so you can track variables that are in different places over
their entire life. */
-typedef struct dw_loc_list_struct
+typedef struct dw_loc_list_struct GTY(())
{
dw_loc_list_ref dw_loc_next;
const char *begin; /* Label for begin address of range */
@@ -2310,6 +2402,8 @@ typedef struct dw_loc_list_struct
dw_loc_descr_ref expr;
} dw_loc_list_node;
+#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
+
static const char *dwarf_stack_op_name PARAMS ((unsigned));
static dw_loc_descr_ref new_loc_descr PARAMS ((enum dwarf_location_atom,
unsigned long,
@@ -2645,10 +2739,8 @@ new_loc_descr (op, oprnd1, oprnd2)
unsigned long oprnd1;
unsigned long oprnd2;
{
- /* Use xcalloc here so we clear out all of the long_long constant in
- the union. */
dw_loc_descr_ref descr
- = (dw_loc_descr_ref) xcalloc (1, sizeof (dw_loc_descr_node));
+ = (dw_loc_descr_ref) ggc_alloc_cleared (sizeof (dw_loc_descr_node));
descr->dw_loc_opc = op;
descr->dw_loc_oprnd1.val_class = dw_val_class_unsigned_const;
@@ -3134,10 +3226,7 @@ get_cfa_from_loc_descr (cfa, loc)
#ifdef DWARF2_DEBUGGING_INFO
/* .debug_str support. */
-static hashnode indirect_string_alloc PARAMS ((hash_table *));
-static int output_indirect_string PARAMS ((struct cpp_reader *,
- hashnode, const PTR));
-
+static int output_indirect_string PARAMS ((void **, void *));
static void dwarf2out_init PARAMS ((const char *));
static void dwarf2out_finish PARAMS ((const char *));
@@ -3179,6 +3268,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
dwarf2out_abstract_function, /* outlining_inline_function */
debug_nothing_rtx /* label */
};
+#endif
/* NOTE: In the comments in this file, many references are made to
"Debugging Information Entries". This term is abbreviated as `DIE'
@@ -3207,7 +3297,7 @@ typedef struct dw_ranges_struct *dw_ranges_ref;
entry. The label gives the PC value associated with
the line number entry. */
-typedef struct dw_line_info_struct
+typedef struct dw_line_info_struct GTY(())
{
unsigned long dw_file_num;
unsigned long dw_line_num;
@@ -3216,7 +3306,7 @@ dw_line_info_entry;
/* Line information for functions in separate sections; each one gets its
own sequence. */
-typedef struct dw_separate_line_info_struct
+typedef struct dw_separate_line_info_struct GTY(())
{
unsigned long dw_file_num;
unsigned long dw_line_num;
@@ -3228,7 +3318,7 @@ dw_separate_line_info_entry;
a link to the next attribute in the chain, and an attribute value.
Attributes are typically linked below the DIE they modify. */
-typedef struct dw_attr_struct
+typedef struct dw_attr_struct GTY(())
{
enum dwarf_attribute dw_attr;
dw_attr_ref dw_attr_next;
@@ -3238,7 +3328,7 @@ dw_attr_node;
/* The Debugging Information Entry (DIE) structure */
-typedef struct die_struct
+typedef struct die_struct GTY(())
{
enum dwarf_tag die_tag;
char *die_symbol;
@@ -3254,20 +3344,20 @@ die_node;
/* The pubname structure */
-typedef struct pubname_struct
+typedef struct pubname_struct GTY(())
{
dw_die_ref die;
char *name;
}
pubname_entry;
-struct dw_ranges_struct
+struct dw_ranges_struct GTY(())
{
int block_num;
};
/* The limbo die list structure. */
-typedef struct limbo_die_struct
+typedef struct limbo_die_struct GTY(())
{
dw_die_ref die;
tree created_for;
@@ -3351,14 +3441,14 @@ limbo_die_node;
static unsigned long next_die_offset;
/* Record the root of the DIE's built for the current compilation unit. */
-static dw_die_ref comp_unit_die;
+static GTY(()) dw_die_ref comp_unit_die;
/* We need special handling in dwarf2out_start_source_file if it is
first one. */
static int is_main_source;
/* A list of DIEs with a NULL parent waiting to be relocated. */
-static limbo_die_node *limbo_die_list = 0;
+static GTY(()) limbo_die_node *limbo_die_list;
/* Structure used by lookup_filename to manage sets of filenames. */
struct file_table
@@ -3379,7 +3469,7 @@ static struct file_table file_table;
/* A pointer to the base of a table of references to DIE's that describe
declarations. The table is indexed by DECL_UID() which is a unique
number identifying each decl. */
-static dw_die_ref *decl_die_table;
+static GTY((length ("decl_die_table_allocated"))) dw_die_ref *decl_die_table;
/* Number of elements currently allocated for the decl_die_table. */
static unsigned decl_die_table_allocated;
@@ -3394,7 +3484,8 @@ static unsigned decl_die_table_in_use;
/* A pointer to the base of a list of references to DIE's that
are uniquely identified by their tag, presence/absence of
children DIE's, and list of attribute/value pairs. */
-static dw_die_ref *abbrev_die_table;
+static GTY((length ("abbrev_die_table_allocated")))
+ dw_die_ref *abbrev_die_table;
/* Number of elements currently allocated for abbrev_die_table. */
static unsigned abbrev_die_table_allocated;
@@ -3408,23 +3499,25 @@ static unsigned abbrev_die_table_in_use;
/* A pointer to the base of a table that contains line information
for each source code line in .text in the compilation unit. */
-static dw_line_info_ref line_info_table;
+static GTY((length ("line_info_table_allocated")))
+ dw_line_info_ref line_info_table;
/* Number of elements currently allocated for line_info_table. */
static unsigned line_info_table_allocated;
-/* Number of elements in separate_line_info_table currently in use. */
-static unsigned separate_line_info_table_in_use;
+/* Number of elements in line_info_table currently in use. */
+static unsigned line_info_table_in_use;
/* A pointer to the base of a table that contains line information
for each source code line outside of .text in the compilation unit. */
-static dw_separate_line_info_ref separate_line_info_table;
+static GTY ((length ("separate_line_info_table_allocated")))
+ dw_separate_line_info_ref separate_line_info_table;
/* Number of elements currently allocated for separate_line_info_table. */
static unsigned separate_line_info_table_allocated;
-/* Number of elements in line_info_table currently in use. */
-static unsigned line_info_table_in_use;
+/* Number of elements in separate_line_info_table currently in use. */
+static unsigned separate_line_info_table_in_use;
/* Size (in elements) of increments by which we may expand the
line_info_table. */
@@ -3432,7 +3525,7 @@ static unsigned line_info_table_in_use;
/* A pointer to the base of a table that contains a list of publicly
accessible names. */
-static pubname_ref pubname_table;
+static GTY ((length ("pubname_table_allocated"))) pubname_ref pubname_table;
/* Number of elements currently allocated for pubname_table. */
static unsigned pubname_table_allocated;
@@ -3445,7 +3538,7 @@ static unsigned pubname_table_in_use;
#define PUBNAME_TABLE_INCREMENT 64
/* Array of dies for which we should generate .debug_arange info. */
-static dw_die_ref *arange_table;
+static GTY((length ("arange_table_allocated"))) dw_die_ref *arange_table;
/* Number of elements currently allocated for arange_table. */
static unsigned arange_table_allocated;
@@ -3458,7 +3551,7 @@ static unsigned arange_table_in_use;
#define ARANGE_TABLE_INCREMENT 64
/* Array of dies for which we should generate .debug_ranges info. */
-static dw_ranges_ref ranges_table;
+static GTY ((length ("ranges_table_allocated"))) dw_ranges_ref ranges_table;
/* Number of elements currently allocated for ranges_table. */
static unsigned ranges_table_allocated;
@@ -3479,6 +3572,8 @@ static int current_function_has_inlines;
static int comp_unit_has_inlines;
#endif
+#ifdef DWARF2_DEBUGGING_INFO
+
/* Forward declarations for functions defined in this file. */
static int is_pseudo_reg PARAMS ((rtx));
@@ -3494,7 +3589,7 @@ static tree decl_ultimate_origin PARAMS ((tree));
static tree block_ultimate_origin PARAMS ((tree));
static tree decl_class_context PARAMS ((tree));
static void add_dwarf_attr PARAMS ((dw_die_ref, dw_attr_ref));
-static inline dw_val_class AT_class PARAMS ((dw_attr_ref));
+static inline enum dw_val_class AT_class PARAMS ((dw_attr_ref));
static void add_AT_flag PARAMS ((dw_die_ref,
enum dwarf_attribute,
unsigned));
@@ -3513,6 +3608,8 @@ static void add_AT_long_long PARAMS ((dw_die_ref,
static void add_AT_float PARAMS ((dw_die_ref,
enum dwarf_attribute,
unsigned, long *));
+static hashval_t debug_str_do_hash PARAMS ((const void *));
+static int debug_str_eq PARAMS ((const void *, const void *));
static void add_AT_string PARAMS ((dw_die_ref,
enum dwarf_attribute,
const char *));
@@ -3737,7 +3834,6 @@ static void add_loc_descr_to_loc_list PARAMS ((dw_loc_list_ref *,
const char *, const char *, const char *));
static void output_loc_list PARAMS ((dw_loc_list_ref));
static char *gen_internal_sym PARAMS ((const char *));
-static void mark_limbo_die_list PARAMS ((void *));
/* Section names used to hold DWARF debugging information. */
#ifndef DEBUG_INFO_SECTION
@@ -4404,7 +4500,7 @@ add_dwarf_attr (die, attr)
}
}
-static inline dw_val_class
+static inline enum dw_val_class
AT_class (a)
dw_attr_ref a;
{
@@ -4419,7 +4515,7 @@ add_AT_flag (die, attr_kind, flag)
enum dwarf_attribute attr_kind;
unsigned flag;
{
- dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
@@ -4446,7 +4542,7 @@ add_AT_int (die, attr_kind, int_val)
enum dwarf_attribute attr_kind;
long int int_val;
{
- dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
@@ -4473,7 +4569,7 @@ add_AT_unsigned (die, attr_kind, unsigned_val)
enum dwarf_attribute attr_kind;
unsigned long unsigned_val;
{
- dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
@@ -4501,7 +4597,7 @@ add_AT_long_long (die, attr_kind, val_hi, val_low)
unsigned long val_hi;
unsigned long val_low;
{
- dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
@@ -4520,7 +4616,7 @@ add_AT_float (die, attr_kind, length, array)
unsigned length;
long *array;
{
- dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
@@ -4530,6 +4626,24 @@ add_AT_float (die, attr_kind, length, array)
add_dwarf_attr (die, attr);
}
+/* Hash and equality functions for debug_str_hash. */
+
+static hashval_t
+debug_str_do_hash (x)
+ const void * x;
+{
+ return htab_hash_string (((const struct indirect_string_node *)x)->str);
+}
+
+static int
+debug_str_eq (x1, x2)
+ const void * x1;
+ const void * x2;
+{
+ return strcmp ((((const struct indirect_string_node *)x1)->str),
+ (const char *)x2) == 0;
+}
+
/* Add a string attribute value to a DIE. */
static inline void
@@ -4538,18 +4652,20 @@ add_AT_string (die, attr_kind, str)
enum dwarf_attribute attr_kind;
const char *str;
{
- dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
struct indirect_string_node *node;
+ PTR *slot;
if (! debug_str_hash)
- {
- debug_str_hash = ht_create (10);
- debug_str_hash->alloc_node = indirect_string_alloc;
- }
-
- node = (struct indirect_string_node *)
- ht_lookup (debug_str_hash, (const unsigned char *) str,
- strlen (str), HT_ALLOC);
+ debug_str_hash = htab_create_ggc (10, debug_str_do_hash,
+ debug_str_eq, NULL);
+
+ slot = htab_find_slot_with_hash (debug_str_hash, str,
+ htab_hash_string (str), INSERT);
+ if (*slot == NULL)
+ *slot = ggc_alloc_cleared (sizeof (struct indirect_string_node));
+ node = (struct indirect_string_node *) *slot;
+ node->str = ggc_alloc_string (str, -1);
node->refcount++;
attr->dw_attr_next = NULL;
@@ -4564,7 +4680,7 @@ AT_string (a)
dw_attr_ref a;
{
if (a && AT_class (a) == dw_val_class_str)
- return (const char *) HT_STR (&a->dw_attr_val.v.val_str->id);
+ return a->dw_attr_val.v.val_str->str;
abort ();
}
@@ -4580,14 +4696,13 @@ AT_string_form (a)
{
struct indirect_string_node *node;
unsigned int len;
- extern int const_labelno;
char label[32];
node = a->dw_attr_val.v.val_str;
if (node->form)
return node->form;
- len = HT_LEN (&node->id) + 1;
+ len = strlen (node->str) + 1;
/* If the string is shorter or equal to the size of the reference, it is
always better to put it inline. */
@@ -4601,8 +4716,8 @@ AT_string_form (a)
&& (len - DWARF_OFFSET_SIZE) * node->refcount <= len)
return node->form = DW_FORM_string;
- ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno);
- ++const_labelno;
+ ASM_GENERATE_INTERNAL_LABEL (label, "LASF", dw2_string_counter);
+ ++dw2_string_counter;
node->label = xstrdup (label);
return node->form = DW_FORM_strp;
@@ -4619,7 +4734,7 @@ add_AT_die_ref (die, attr_kind, targ_die)
enum dwarf_attribute attr_kind;
dw_die_ref targ_die;
{
- dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
@@ -4668,7 +4783,7 @@ add_AT_fde_ref (die, attr_kind, targ_fde)
enum dwarf_attribute attr_kind;
unsigned targ_fde;
{
- dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
@@ -4685,7 +4800,7 @@ add_AT_loc (die, attr_kind, loc)
enum dwarf_attribute attr_kind;
dw_loc_descr_ref loc;
{
- dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
@@ -4710,7 +4825,7 @@ add_AT_loc_list (die, attr_kind, loc_list)
enum dwarf_attribute attr_kind;
dw_loc_list_ref loc_list;
{
- dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
@@ -4738,7 +4853,7 @@ add_AT_addr (die, attr_kind, addr)
enum dwarf_attribute attr_kind;
rtx addr;
{
- dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
@@ -4765,7 +4880,7 @@ add_AT_lbl_id (die, attr_kind, lbl_id)
enum dwarf_attribute attr_kind;
const char *lbl_id;
{
- dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
@@ -4782,7 +4897,7 @@ add_AT_lbl_offset (die, attr_kind, label)
enum dwarf_attribute attr_kind;
const char *label;
{
- dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
@@ -4799,7 +4914,7 @@ add_AT_offset (die, attr_kind, offset)
enum dwarf_attribute attr_kind;
unsigned long offset;
{
- dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
@@ -4816,7 +4931,7 @@ add_AT_range_list (die, attr_kind, offset)
enum dwarf_attribute attr_kind;
unsigned long offset;
{
- dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
@@ -4976,27 +5091,9 @@ static inline void
free_AT (a)
dw_attr_ref a;
{
- switch (AT_class (a))
- {
- case dw_val_class_str:
- if (a->dw_attr_val.v.val_str->refcount)
- a->dw_attr_val.v.val_str->refcount--;
- break;
-
- case dw_val_class_lbl_id:
- case dw_val_class_lbl_offset:
- free (a->dw_attr_val.v.val_lbl_id);
- break;
-
- case dw_val_class_float:
- free (a->dw_attr_val.v.val_float.array);
- break;
-
- default:
- break;
- }
-
- free (a);
+ if (AT_class (a) == dw_val_class_str)
+ if (a->dw_attr_val.v.val_str->refcount)
+ a->dw_attr_val.v.val_str->refcount--;
}
/* Remove the specified attribute if present. */
@@ -5031,7 +5128,6 @@ free_die (die)
dw_die_ref die;
{
remove_children (die);
- free (die);
}
/* Discard the children of this DIE. */
@@ -5124,7 +5220,7 @@ new_die (tag_value, parent_die, t)
dw_die_ref parent_die;
tree t;
{
- dw_die_ref die = (dw_die_ref) xcalloc (1, sizeof (die_node));
+ dw_die_ref die = (dw_die_ref) ggc_alloc_cleared (sizeof (die_node));
die->die_tag = tag_value;
@@ -5134,7 +5230,7 @@ new_die (tag_value, parent_die, t)
{
limbo_die_node *limbo_node;
- limbo_node = (limbo_die_node *) xmalloc (sizeof (limbo_die_node));
+ limbo_node = ggc_alloc_cleared (sizeof (limbo_die_node));
limbo_node->die = die;
limbo_node->created_for = t;
limbo_node->next = limbo_die_list;
@@ -5191,9 +5287,8 @@ equate_decl_number_to_die (decl, decl_die)
/ DECL_DIE_TABLE_INCREMENT)
* DECL_DIE_TABLE_INCREMENT;
- decl_die_table
- = (dw_die_ref *) xrealloc (decl_die_table,
- sizeof (dw_die_ref) * num_allocated);
+ decl_die_table = ggc_realloc (decl_die_table,
+ sizeof (dw_die_ref) * num_allocated);
memset ((char *) &decl_die_table[decl_die_table_allocated], 0,
(num_allocated - decl_die_table_allocated) * sizeof (dw_die_ref));
@@ -5605,8 +5700,7 @@ same_dw_val_p (v1, v2, mark)
case dw_val_class_flag:
return v1->v.val_flag == v2->v.val_flag;
case dw_val_class_str:
- return !strcmp((const char *) HT_STR (&v1->v.val_str->id),
- (const char *) HT_STR (&v2->v.val_str->id));
+ return !strcmp(v1->v.val_str->str, v2->v.val_str->str);
case dw_val_class_addr:
r1 = v1->v.val_addr;
@@ -6145,9 +6239,8 @@ build_abbrev_table (die)
if (abbrev_die_table_in_use >= abbrev_die_table_allocated)
{
n_alloc = abbrev_die_table_allocated + ABBREV_DIE_TABLE_INCREMENT;
- abbrev_die_table
- = (dw_die_ref *) xrealloc (abbrev_die_table,
- sizeof (dw_die_ref) * n_alloc);
+ abbrev_die_table = ggc_realloc (abbrev_die_table,
+ sizeof (dw_die_ref) * n_alloc);
memset ((char *) &abbrev_die_table[abbrev_die_table_allocated], 0,
(n_alloc - abbrev_die_table_allocated) * sizeof (dw_die_ref));
@@ -6249,7 +6342,7 @@ size_of_die (die)
if (AT_string_form (a) == DW_FORM_strp)
size += DWARF_OFFSET_SIZE;
else
- size += HT_LEN (&a->dw_attr_val.v.val_str->id) + 1;
+ size += strlen (a->dw_attr_val.v.val_str->str) + 1;
break;
default:
abort ();
@@ -6529,8 +6622,7 @@ new_loc_list (expr, begin, end, section, gensym)
const char *section;
unsigned gensym;
{
- dw_loc_list_ref retlist
- = (dw_loc_list_ref) xcalloc (1, sizeof (dw_loc_list_node));
+ dw_loc_list_ref retlist = ggc_alloc_cleared (sizeof (dw_loc_list_node));
retlist->begin = begin;
retlist->end = end;
@@ -6884,9 +6976,11 @@ add_pubname (decl, die)
{
pubname_table_allocated += PUBNAME_TABLE_INCREMENT;
pubname_table
- = (pubname_ref) xrealloc (pubname_table,
- (pubname_table_allocated
- * sizeof (pubname_entry)));
+ = (pubname_ref) ggc_realloc (pubname_table,
+ (pubname_table_allocated
+ * sizeof (pubname_entry)));
+ memset (pubname_table + pubname_table_in_use, 0,
+ PUBNAME_TABLE_INCREMENT * sizeof (pubname_entry));
}
p = &pubname_table[pubname_table_in_use++];
@@ -6942,8 +7036,11 @@ add_arange (decl, die)
if (arange_table_in_use == arange_table_allocated)
{
arange_table_allocated += ARANGE_TABLE_INCREMENT;
- arange_table = (dw_die_ref *)
- xrealloc (arange_table, arange_table_allocated * sizeof (dw_die_ref));
+ arange_table = ggc_realloc (arange_table,
+ (arange_table_allocated
+ * sizeof (dw_die_ref)));
+ memset (arange_table + arange_table_in_use, 0,
+ ARANGE_TABLE_INCREMENT * sizeof (dw_die_ref));
}
arange_table[arange_table_in_use++] = die;
@@ -7038,8 +7135,10 @@ add_ranges (block)
{
ranges_table_allocated += RANGES_TABLE_INCREMENT;
ranges_table = (dw_ranges_ref)
- xrealloc (ranges_table, (ranges_table_allocated
- * sizeof (struct dw_ranges_struct)));
+ ggc_realloc (ranges_table, (ranges_table_allocated
+ * sizeof (struct dw_ranges_struct)));
+ memset (ranges_table + ranges_table_in_use, 0,
+ RANGES_TABLE_INCREMENT * sizeof (struct dw_ranges_struct));
}
ranges_table[in_use].block_num = (block ? BLOCK_NUMBER (block) : 0);
@@ -9090,7 +9189,7 @@ add_const_value_attribute (die, rtl)
if (GET_MODE_CLASS (mode) == MODE_FLOAT)
{
unsigned length = GET_MODE_SIZE (mode) / 4;
- long *array = (long *) xmalloc (sizeof (long) * length);
+ long *array = (long *) ggc_alloc (sizeof (long) * length);
REAL_VALUE_TYPE rv;
REAL_VALUE_FROM_CONST_DOUBLE (rv, rtl);
@@ -11974,15 +12073,6 @@ gen_decl_die (decl, context_die)
abort ();
}
}
-
-static void
-mark_limbo_die_list (ptr)
- void *ptr ATTRIBUTE_UNUSED;
-{
- limbo_die_node *node;
- for (node = limbo_die_list; node; node = node->next)
- ggc_mark_tree (node->created_for);
-}
/* Add Ada "use" clause information for SGI Workshop debugger. */
@@ -12225,6 +12315,8 @@ lookup_filename (file_name)
file_table.allocated = i + FILE_TABLE_INCREMENT;
file_table.table = (char **)
xrealloc (file_table.table, file_table.allocated * sizeof (char *));
+ memset (file_table.table + i, 0,
+ FILE_TABLE_INCREMENT * sizeof (char *));
}
/* Add the new entry to the end of the filename table. */
@@ -12299,9 +12391,14 @@ dwarf2out_source_line (line, filename)
separate_line_info_table_allocated += LINE_INFO_TABLE_INCREMENT;
separate_line_info_table
= (dw_separate_line_info_ref)
- xrealloc (separate_line_info_table,
- separate_line_info_table_allocated
- * sizeof (dw_separate_line_info_entry));
+ ggc_realloc (separate_line_info_table,
+ separate_line_info_table_allocated
+ * sizeof (dw_separate_line_info_entry));
+ memset ((separate_line_info_table
+ + separate_line_info_table_in_use),
+ 0,
+ (LINE_INFO_TABLE_INCREMENT
+ * sizeof (dw_separate_line_info_entry)));
}
/* Add the new entry at the end of the line_info_table. */
@@ -12323,10 +12420,11 @@ dwarf2out_source_line (line, filename)
{
line_info_table_allocated += LINE_INFO_TABLE_INCREMENT;
line_info_table
- = (dw_line_info_ref)
- xrealloc (line_info_table,
- (line_info_table_allocated
- * sizeof (dw_line_info_entry)));
+ = ggc_realloc (line_info_table,
+ (line_info_table_allocated
+ * sizeof (dw_line_info_entry)));
+ memset (line_info_table + line_info_table_in_use, 0,
+ LINE_INFO_TABLE_INCREMENT * sizeof (dw_line_info_entry));
}
/* Add the new entry at the end of the line_info_table. */
@@ -12433,8 +12531,8 @@ dwarf2out_init (main_input_filename)
lookup_filename (main_input_filename);
/* Allocate the initial hunk of the decl_die_table. */
- decl_die_table
- = (dw_die_ref *) xcalloc (DECL_DIE_TABLE_INCREMENT, sizeof (dw_die_ref));
+ decl_die_table = ggc_alloc_cleared (DECL_DIE_TABLE_INCREMENT
+ * sizeof (dw_die_ref));
decl_die_table_allocated = DECL_DIE_TABLE_INCREMENT;
decl_die_table_in_use = 0;
@@ -12442,17 +12540,15 @@ dwarf2out_init (main_input_filename)
VARRAY_TREE_INIT (decl_scope_table, 256, "decl_scope_table");
/* Allocate the initial hunk of the abbrev_die_table. */
- abbrev_die_table
- = (dw_die_ref *) xcalloc (ABBREV_DIE_TABLE_INCREMENT,
- sizeof (dw_die_ref));
+ abbrev_die_table = ggc_alloc_cleared (ABBREV_DIE_TABLE_INCREMENT
+ * sizeof (dw_die_ref));
abbrev_die_table_allocated = ABBREV_DIE_TABLE_INCREMENT;
/* Zero-th entry is allocated, but unused */
abbrev_die_table_in_use = 1;
/* Allocate the initial hunk of the line_info_table. */
- line_info_table
- = (dw_line_info_ref) xcalloc (LINE_INFO_TABLE_INCREMENT,
- sizeof (dw_line_info_entry));
+ line_info_table = ggc_alloc_cleared (LINE_INFO_TABLE_INCREMENT
+ * sizeof (dw_line_info_entry));
line_info_table_allocated = LINE_INFO_TABLE_INCREMENT;
/* Zero-th entry is allocated, but unused */
@@ -12470,8 +12566,6 @@ dwarf2out_init (main_input_filename)
VARRAY_RTX_INIT (used_rtx_varray, 32, "used_rtx_varray");
- ggc_add_root (&limbo_die_list, 1, 1, mark_limbo_die_list);
-
ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label,
DEBUG_ABBREV_SECTION_LABEL, 0);
@@ -12508,39 +12602,21 @@ dwarf2out_init (main_input_filename)
}
}
-/* Allocate a string in .debug_str hash table. */
-
-static hashnode
-indirect_string_alloc (tab)
- hash_table *tab ATTRIBUTE_UNUSED;
-{
- struct indirect_string_node *node;
-
- node = xmalloc (sizeof (struct indirect_string_node));
- node->refcount = 0;
- node->form = 0;
- node->label = NULL;
-
- return (hashnode) node;
-}
-
/* A helper function for dwarf2out_finish called through
ht_forall. Emit one queued .debug_str string. */
static int
-output_indirect_string (pfile, h, v)
- struct cpp_reader *pfile ATTRIBUTE_UNUSED;
- hashnode h;
- const PTR v ATTRIBUTE_UNUSED;
+output_indirect_string (h, v)
+ void **h;
+ void *v ATTRIBUTE_UNUSED;
{
- struct indirect_string_node *node = (struct indirect_string_node *) h;
+ struct indirect_string_node *node = (struct indirect_string_node *) *h;
if (node->form == DW_FORM_strp)
{
named_section_flags (DEBUG_STR_SECTION, DEBUG_STR_SECTION_FLAGS);
ASM_OUTPUT_LABEL (asm_out_file, node->label);
- assemble_string ((const char *) HT_STR (&node->id),
- HT_LEN (&node->id) + 1);
+ assemble_string (node->str, strlen (node->str) + 1);
}
return 1;
@@ -12607,8 +12683,6 @@ dwarf2out_finish (input_filename)
else
abort ();
}
-
- free (node);
}
limbo_die_list = NULL;
@@ -12724,7 +12798,7 @@ dwarf2out_finish (input_filename)
/* If we emitted any DW_FORM_strp form attribute, output the string
table too. */
if (debug_str_hash)
- ht_forall (debug_str_hash, output_indirect_string, NULL);
+ htab_traverse (debug_str_hash, output_indirect_string, NULL);
}
#else
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 0099a50ee3c..eb1814acc78 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -5315,14 +5315,14 @@ init_emit_once (line_numbers)
/* Initialize the CONST_INT, CONST_DOUBLE, and memory attribute hash
tables. */
- const_int_htab = htab_create (37, const_int_htab_hash,
- const_int_htab_eq, NULL);
+ const_int_htab = htab_create_ggc (37, const_int_htab_hash,
+ const_int_htab_eq, NULL);
- const_double_htab = htab_create (37, const_double_htab_hash,
- const_double_htab_eq, NULL);
+ const_double_htab = htab_create_ggc (37, const_double_htab_hash,
+ const_double_htab_eq, NULL);
- mem_attrs_htab = htab_create (37, mem_attrs_htab_hash,
- mem_attrs_htab_eq, NULL);
+ mem_attrs_htab = htab_create_ggc (37, mem_attrs_htab_hash,
+ mem_attrs_htab_eq, NULL);
no_line_numbers = ! line_numbers;
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 0c53604e7d5..3847fc00041 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -1395,7 +1395,7 @@ size_int_type_wide (number, type)
if (size_htab == 0)
{
- size_htab = htab_create (1024, size_htab_hash, size_htab_eq, NULL);
+ size_htab = htab_create_ggc (1024, size_htab_hash, size_htab_eq, NULL);
new_const = make_node (INTEGER_CST);
}
diff --git a/gcc/function.c b/gcc/function.c
index 0a0f56d2375..1c972d2cff4 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -125,7 +125,7 @@ int current_function_uses_only_leaf_regs;
int virtuals_instantiated;
/* Assign unique numbers to labels generated for profiling, debugging, etc. */
-static int funcdef_no;
+static GTY(()) int funcdef_no;
/* These variables hold pointers to functions to create and destroy
target specific, per-function data structures. */
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 618d2723208..8b27a0ac579 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -421,6 +421,7 @@ or with constant text in a single argument.
%w marks the argument containing or following the %w as the
"output file" of this compilation. This puts the argument
into the sequence of arguments that %o will substitute later.
+ %V indicates that this compilation produces no "output file".
%W{...}
like %{...} but mark last argument supplied within
as a file to be deleted on failure.
@@ -914,9 +915,19 @@ static const struct compiler default_compilers[] =
%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)", 0},
{".h", "@c-header", 0},
{"@c-header",
- "%{!E:%ecompilation of header file requested} \
- %(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)",
- 0},
+ /* cc1 has an integrated ISO C preprocessor. We should invoke the
+ external preprocessor if -save-temps is given. */
+ "%{E|M|MM:%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)}\
+ %{!E:%{!M:%{!MM:\
+ %{save-temps|traditional-cpp:%(trad_capable_cpp) \
+ %(cpp_options) %b.i \n\
+ cc1 -fpreprocessed %b.i %(cc1_options)\
+ -o %g.s %{!o*:--output-pch=%i.pch}\
+ %W{o*:--output-pch=%*}%V}\
+ %{!save-temps:%{!traditional-cpp:\
+ cc1 %(cpp_unique_options) %(cc1_options)\
+ -o %g.s %{!o*:--output-pch=%i.pch}\
+ %W{o*:--output-pch=%*}%V}}}}}", 0},
{".i", "@cpp-output", 0},
{"@cpp-output",
"%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}", 0},
@@ -4765,6 +4776,10 @@ do_spec_1 (spec, inswitch, soft_matched_part)
this_is_library_file = 1;
break;
+ case 'V':
+ outfiles[input_file_number] = NULL;
+ break;
+
case 'w':
this_is_output_file = 1;
break;
@@ -6079,6 +6094,7 @@ main (argc, argv)
size_t i;
int value;
int linker_was_run = 0;
+ int num_linker_inputs = 0;
char *explicit_link_files;
char *specs_file;
const char *p;
@@ -6516,9 +6532,15 @@ main (argc, argv)
error_count++;
}
+ /* Determine if there are any linker input files. */
+ num_linker_inputs = 0;
+ for (i = 0; (int) i < n_infiles; i++)
+ if (explicit_link_files[i] || outfiles[i] != NULL)
+ num_linker_inputs++;
+
/* Run ld to link all the compiler output files. */
- if (error_count == 0)
+ if (num_linker_inputs > 0 && error_count == 0)
{
int tmp = execution_count;
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index 855e5edfe96..b279263b548 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -603,14 +603,6 @@ adjust_field_rtx_def (t, opt)
subfields->opt->name = "skip";
subfields->opt->info = NULL;
}
- else if ((size_t) rtx_next[i] == aindex)
- {
- /* The 'next' field will be marked by the chain_next option. */
- subfields->opt = xmalloc (sizeof (*subfields->opt));
- subfields->opt->next = nodot;
- subfields->opt->name = "skip";
- subfields->opt->info = NULL;
- }
else
subfields->opt = nodot;
}
@@ -1364,70 +1356,78 @@ struct flist {
outf_p f;
};
-static void output_escaped_param PARAMS ((outf_p , const char *, const char *,
- const char *, const char *,
- struct fileloc *));
+struct walk_type_data;
+
+/* For scalars and strings, given the item in 'val'.
+ For structures, given a pointer to the item in 'val'.
+ For misc. pointers, given the item in 'val'.
+*/
+typedef void (*process_field_fn)
+ PARAMS ((type_p f, const struct walk_type_data *p));
+typedef void (*func_name_fn)
+ PARAMS ((type_p s, const struct walk_type_data *p));
+
+/* Parameters for write_types. */
+
+struct write_types_data
+{
+ const char *prefix;
+ const char *param_prefix;
+ const char *subfield_marker_routine;
+ const char *marker_routine;
+ const char *reorder_note_routine;
+ const char *comment;
+};
+
+static void output_escaped_param PARAMS ((struct walk_type_data *d,
+ const char *, const char *));
static void output_mangled_typename PARAMS ((outf_p, type_p));
-static void write_gc_structure_fields
- PARAMS ((outf_p , type_p, const char *, const char *, options_p,
- int, struct fileloc *, lang_bitmap, type_p *));
-static void write_gc_marker_routine_for_structure PARAMS ((type_p, type_p,
- type_p *));
-static void write_gc_types PARAMS ((type_p structures, type_p param_structs));
+static void walk_type PARAMS ((type_p t, struct walk_type_data *d));
+static void write_func_for_structure
+ PARAMS ((type_p orig_s, type_p s, type_p * param,
+ const struct write_types_data *wtd));
+static void write_types_process_field
+ PARAMS ((type_p f, const struct walk_type_data *d));
+static void write_types PARAMS ((type_p structures,
+ type_p param_structs,
+ const struct write_types_data *wtd));
+static void write_types_local_process_field
+ PARAMS ((type_p f, const struct walk_type_data *d));
+static void write_local_func_for_structure
+ PARAMS ((type_p orig_s, type_p s, type_p * param));
+static void write_local PARAMS ((type_p structures,
+ type_p param_structs));
static void write_enum_defn PARAMS ((type_p structures, type_p param_structs));
+static int contains_scalar_p PARAMS ((type_p t));
static void put_mangled_filename PARAMS ((outf_p , const char *));
static void finish_root_table PARAMS ((struct flist *flp, const char *pfx,
const char *tname, const char *lastname,
const char *name));
-static void write_gc_root PARAMS ((outf_p , pair_p, type_p, const char *, int,
+static void write_root PARAMS ((outf_p , pair_p, type_p, const char *, int,
struct fileloc *, const char *));
-static void write_gc_roots PARAMS ((pair_p));
+static void write_array PARAMS ((outf_p f, pair_p v,
+ const struct write_types_data *wtd));
+static void write_roots PARAMS ((pair_p));
-static int gc_counter;
+/* Parameters for walk_type. */
-/* Print PARAM to OF processing escapes. VAL references the current object,
- PREV_VAL the object containing the current object, ONAME is the name
- of the option and LINE is used to print error messages. */
-
-static void
-output_escaped_param (of, param, val, prev_val, oname, line)
- outf_p of;
- const char *param;
- const char *val;
- const char *prev_val;
- const char *oname;
- struct fileloc *line;
+struct walk_type_data
{
- const char *p;
-
- for (p = param; *p; p++)
- if (*p != '%')
- oprintf (of, "%c", *p);
- else switch (*++p)
- {
- case 'h':
- oprintf (of, "(%s)", val);
- break;
- case '0':
- oprintf (of, "(*x)");
- break;
- case '1':
- oprintf (of, "(%s)", prev_val);
- break;
- case 'a':
- {
- const char *pp = val + strlen (val);
- while (pp[-1] == ']')
- while (*pp != '[')
- pp--;
- oprintf (of, "%s", pp);
- }
- break;
- default:
- error_at_line (line, "`%s' option contains bad escape %c%c",
- oname, '%', *p);
- }
-}
+ process_field_fn process_field;
+ const void *cookie;
+ outf_p of;
+ options_p opt;
+ const char *val;
+ const char *prev_val[4];
+ int indent;
+ int counter;
+ struct fileloc *line;
+ lang_bitmap bitmap;
+ type_p *param;
+ int used_length;
+ type_p orig_s;
+ const char *reorder_fn;
+};
/* Print a mangled name representing T to OF. */
@@ -1469,423 +1469,491 @@ output_mangled_typename (of, t)
}
}
-/* Write out code to OF which marks the fields of S. VAL references
- the current object, PREV_VAL the object containing the current
- object, OPTS is a list of options to apply, INDENT is the current
- indentation level, LINE is used to print error messages, BITMAP
- indicates which languages to print the structure for, and PARAM is
- the current parameter (from an enclosing param_is option). */
+/* Print PARAM to D->OF processing escapes. D->VAL references the
+ current object, D->PREV_VAL the object containing the current
+ object, ONAME is the name of the option and D->LINE is used to
+ print error messages. */
static void
-write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap,
- param)
- outf_p of;
- type_p s;
- const char *val;
- const char *prev_val;
- options_p opts;
- int indent;
- struct fileloc *line;
- lang_bitmap bitmap;
- type_p * param;
+output_escaped_param (d, param, oname)
+ struct walk_type_data *d;
+ const char *param;
+ const char *oname;
{
- pair_p f;
- int seen_default = 0;
-
- if (! s->u.s.line.file)
- error_at_line (line, "incomplete structure `%s'", s->u.s.tag);
- else if ((s->u.s.bitmap & bitmap) != bitmap)
- {
- error_at_line (line, "structure defined for mismatching languages");
- error_at_line (&s->u.s.line, "one structure defined here");
- }
+ const char *p;
- if (s->kind == TYPE_UNION)
- {
- const char *tagexpr = NULL;
- options_p oo;
-
- for (oo = opts; oo; oo = oo->next)
- if (strcmp (oo->name, "desc") == 0)
- tagexpr = (const char *)oo->info;
- if (tagexpr == NULL)
+ for (p = param; *p; p++)
+ if (*p != '%')
+ oprintf (d->of, "%c", *p);
+ else switch (*++p)
+ {
+ case 'h':
+ oprintf (d->of, "(%s)", d->prev_val[2]);
+ break;
+ case '0':
+ oprintf (d->of, "(%s)", d->prev_val[0]);
+ break;
+ case '1':
+ oprintf (d->of, "(%s)", d->prev_val[1]);
+ break;
+ case 'a':
{
- tagexpr = "1";
- error_at_line (line, "missing `desc' option");
+ const char *pp = d->val + strlen (d->val);
+ while (pp[-1] == ']')
+ while (*pp != '[')
+ pp--;
+ oprintf (d->of, "%s", pp);
}
+ break;
+ default:
+ error_at_line (d->line, "`%s' option contains bad escape %c%c",
+ oname, '%', *p);
+ }
+}
- oprintf (of, "%*sswitch (", indent, "");
- output_escaped_param (of, tagexpr, val, prev_val, "desc", line);
- oprintf (of, ")\n");
- indent += 2;
- oprintf (of, "%*s{\n", indent, "");
- }
-
- for (f = s->u.s.fields; f; f = f->next)
- {
- const char *tagid = NULL;
- const char *length = NULL;
- int skip_p = 0;
- int default_p = 0;
- int maybe_undef_p = 0;
- int use_param_num = -1;
- int use_params_p = 0;
- int needs_cast_p = 0;
- options_p oo;
- type_p t = f->type;
- const char *dot = ".";
-
- for (oo = f->opt; oo; oo = oo->next)
- if (strcmp (oo->name, "length") == 0)
- length = (const char *)oo->info;
- else if (strcmp (oo->name, "maybe_undef") == 0)
- maybe_undef_p = 1;
- else if (strcmp (oo->name, "tag") == 0)
- tagid = (const char *)oo->info;
- else if (strcmp (oo->name, "special") == 0)
- ;
- else if (strcmp (oo->name, "skip") == 0)
- skip_p = 1;
- else if (strcmp (oo->name, "default") == 0)
- default_p = 1;
- else if (strcmp (oo->name, "desc") == 0)
- ;
- else if (strcmp (oo->name, "descbits") == 0)
- ;
- else if (strcmp (oo->name, "param_is") == 0)
- ;
- else if (strncmp (oo->name, "use_param", 9) == 0
- && (oo->name[9] == '\0' || ISDIGIT (oo->name[9])))
- use_param_num = oo->name[9] == '\0' ? 0 : oo->name[9] - '0';
- else if (strcmp (oo->name, "use_params") == 0)
- use_params_p = 1;
- else if (strcmp (oo->name, "dot") == 0)
- dot = (const char *)oo->info;
- else
- error_at_line (&f->line, "unknown field option `%s'\n", oo->name);
+/* Call D->PROCESS_FIELD for every field (or subfield) of D->VAL,
+ which is of type T. Write code to D->OF to constrain execution (at
+ the point that D->PROCESS_FIELD is called) to the appropriate
+ cases. D->PREV_VAL lists the objects containing the current object,
+ D->OPT is a list of options to apply, D->INDENT is the current
+ indentation level, D->LINE is used to print error messages,
+ D->BITMAP indicates which languages to print the structure for, and
+ D->PARAM is the current parameter (from an enclosing param_is
+ option). */
- if (skip_p)
- continue;
+static void
+walk_type (t, d)
+ type_p t;
+ struct walk_type_data *d;
+{
+ const char *length = NULL;
+ const char *desc = NULL;
+ int maybe_undef_p = 0;
+ int use_param_num = -1;
+ int use_params_p = 0;
+ int needs_cast_p = 0;
+ options_p oo;
+
+ for (oo = d->opt; oo; oo = oo->next)
+ if (strcmp (oo->name, "length") == 0)
+ length = (const char *)oo->info;
+ else if (strcmp (oo->name, "maybe_undef") == 0)
+ maybe_undef_p = 1;
+ else if (strncmp (oo->name, "use_param", 9) == 0
+ && (oo->name[9] == '\0' || ISDIGIT (oo->name[9])))
+ use_param_num = oo->name[9] == '\0' ? 0 : oo->name[9] - '0';
+ else if (strcmp (oo->name, "use_params") == 0)
+ use_params_p = 1;
+ else if (strcmp (oo->name, "desc") == 0)
+ desc = (const char *)oo->info;
+ else if (strcmp (oo->name, "dot") == 0)
+ ;
+ else if (strcmp (oo->name, "tag") == 0)
+ ;
+ else if (strcmp (oo->name, "special") == 0)
+ ;
+ else if (strcmp (oo->name, "skip") == 0)
+ ;
+ else if (strcmp (oo->name, "default") == 0)
+ ;
+ else if (strcmp (oo->name, "descbits") == 0)
+ ;
+ else if (strcmp (oo->name, "param_is") == 0)
+ ;
+ else if (strcmp (oo->name, "chain_next") == 0)
+ ;
+ else if (strcmp (oo->name, "chain_prev") == 0)
+ ;
+ else if (strcmp (oo->name, "reorder") == 0)
+ ;
+ else
+ error_at_line (d->line, "unknown option `%s'\n", oo->name);
- if (use_params_p)
- {
- int pointer_p = t->kind == TYPE_POINTER;
+ if (d->used_length)
+ length = NULL;
- if (pointer_p)
- t = t->u.p;
- t = find_param_structure (t, param);
- if (pointer_p)
- t = create_pointer (t);
- }
+ if (use_params_p)
+ {
+ int pointer_p = t->kind == TYPE_POINTER;
- if (use_param_num != -1)
- {
- if (param != NULL && param[use_param_num] != NULL)
- {
- type_p nt = param[use_param_num];
-
- if (t->kind == TYPE_ARRAY)
- nt = create_array (nt, t->u.a.len);
- else if (length != NULL && t->kind == TYPE_POINTER)
- nt = create_pointer (nt);
- needs_cast_p = (t->kind != TYPE_POINTER
- && nt->kind == TYPE_POINTER);
- t = nt;
- }
- else if (s->kind != TYPE_UNION)
- error_at_line (&f->line, "no parameter defined");
- }
-
- if (t->kind == TYPE_SCALAR
- || (t->kind == TYPE_ARRAY
- && t->u.a.p->kind == TYPE_SCALAR))
- continue;
+ if (pointer_p)
+ t = t->u.p;
+ if (! UNION_OR_STRUCT_P (t))
+ error_at_line (d->line, "`use_params' option on unimplemented type");
+ else
+ t = find_param_structure (t, d->param);
+ if (pointer_p)
+ t = create_pointer (t);
+ }
- seen_default |= default_p;
-
- if (maybe_undef_p
- && (t->kind != TYPE_POINTER
- || t->u.p->kind != TYPE_STRUCT))
- error_at_line (&f->line,
- "field `%s' has invalid option `maybe_undef_p'\n",
- f->name);
- if (s->kind == TYPE_UNION)
+ if (use_param_num != -1)
+ {
+ if (d->param != NULL && d->param[use_param_num] != NULL)
{
- if (tagid)
- {
- oprintf (of, "%*scase %s:\n", indent, "", tagid);
-
- }
- else if (default_p)
- {
- oprintf (of, "%*sdefault:\n", indent, "");
- }
- else
- {
- error_at_line (&f->line, "field `%s' has no tag", f->name);
- continue;
- }
- indent += 2;
+ type_p nt = d->param[use_param_num];
+
+ if (t->kind == TYPE_ARRAY)
+ nt = create_array (nt, t->u.a.len);
+ else if (length != NULL && t->kind == TYPE_POINTER)
+ nt = create_pointer (nt);
+ needs_cast_p = (t->kind != TYPE_POINTER
+ && nt->kind == TYPE_POINTER);
+ t = nt;
}
+ else
+ error_at_line (d->line, "no parameter defined for `%s'",
+ d->val);
+ }
+
+ if (maybe_undef_p
+ && (t->kind != TYPE_POINTER || ! UNION_OR_STRUCT_P (t->u.p)))
+ {
+ error_at_line (d->line,
+ "field `%s' has invalid option `maybe_undef_p'\n",
+ d->val);
+ return;
+ }
+
+ switch (t->kind)
+ {
+ case TYPE_SCALAR:
+ case TYPE_STRING:
+ d->process_field (t, d);
+ break;
- switch (t->kind)
- {
- case TYPE_STRING:
- /* Do nothing; strings go in the string pool. */
- break;
+ case TYPE_POINTER:
+ {
+ if (maybe_undef_p
+ && t->u.p->u.s.line.file == NULL)
+ {
+ oprintf (d->of, "%*sif (%s) abort();\n", d->indent, "", d->val);
+ break;
+ }
- case TYPE_LANG_STRUCT:
+ if (! length)
{
- type_p ti;
- for (ti = t->u.s.lang_struct; ti; ti = ti->next)
- if (ti->u.s.bitmap & bitmap)
- {
- t = ti;
- break;
- }
- if (ti == NULL)
+ if (! UNION_OR_STRUCT_P (t->u.p)
+ && t->u.p->kind != TYPE_PARAM_STRUCT)
{
- error_at_line (&f->line,
- "structure not defined for this language");
+ error_at_line (d->line,
+ "field `%s' is pointer to unimplemented type",
+ d->val);
break;
}
+
+ d->process_field (t->u.p, d);
}
- /* Fall through... */
- case TYPE_STRUCT:
- case TYPE_UNION:
+ else
{
+ int loopcounter = d->counter++;
+ const char *oldval = d->val;
+ const char *oldprevval3 = d->prev_val[3];
char *newval;
- newval = xasprintf ("%s%s%s", val, dot, f->name);
- write_gc_structure_fields (of, t, newval, val, f->opt, indent,
- &f->line, bitmap, param);
+ oprintf (d->of, "%*sif (%s != NULL) {\n", d->indent, "", d->val);
+ d->indent += 2;
+ oprintf (d->of, "%*ssize_t i%d;\n", d->indent, "", loopcounter);
+ d->process_field(t, d);
+ oprintf (d->of, "%*sfor (i%d = 0; i%d < (size_t)(", d->indent, "",
+ loopcounter, loopcounter);
+ output_escaped_param (d, length, "length");
+ oprintf (d->of, "); i%d++) {\n", loopcounter);
+ d->indent += 2;
+ d->val = newval = xasprintf ("%s[i%d]", oldval, loopcounter);
+ d->used_length = 1;
+ d->prev_val[3] = oldval;
+ walk_type (t->u.p, d);
free (newval);
- break;
+ d->val = oldval;
+ d->prev_val[3] = oldprevval3;
+ d->used_length = 0;
+ d->indent -= 2;
+ oprintf (d->of, "%*s}\n", d->indent, "");
+ d->indent -= 2;
+ oprintf (d->of, "%*s}\n", d->indent, "");
}
+ }
+ break;
- case TYPE_POINTER:
- if (! length)
- {
- if (maybe_undef_p
- && t->u.p->u.s.line.file == NULL)
- oprintf (of, "%*sif (%s%s%s) abort();\n", indent, "",
- val, dot, f->name);
- else if (UNION_OR_STRUCT_P (t->u.p)
- || t->u.p->kind == TYPE_PARAM_STRUCT)
- {
- oprintf (of, "%*sgt_ggc_m_", indent, "");
- output_mangled_typename (of, t->u.p);
- oprintf (of, " (");
- if (needs_cast_p)
- oprintf (of, "(%s %s *)",
- UNION_P (t->u.p) ? "union" : "struct",
- t->u.p->u.s.tag);
- oprintf (of, "%s%s%s);\n", val, dot, f->name);
- }
- else
- error_at_line (&f->line, "field `%s' is pointer to scalar",
- f->name);
- break;
- }
- else if (t->u.p->kind == TYPE_SCALAR
- || t->u.p->kind == TYPE_STRING)
- oprintf (of, "%*sggc_mark (%s%s%s);\n", indent, "",
- val, dot, f->name);
- else
- {
- int loopcounter = ++gc_counter;
-
- oprintf (of, "%*sif (%s%s%s != NULL) {\n", indent, "",
- val, dot, f->name);
- indent += 2;
- oprintf (of, "%*ssize_t i%d;\n", indent, "", loopcounter);
- oprintf (of, "%*sggc_set_mark (%s%s%s);\n", indent, "",
- val, dot, f->name);
- oprintf (of, "%*sfor (i%d = 0; i%d < (size_t)(", indent, "",
- loopcounter, loopcounter);
- output_escaped_param (of, length, val, prev_val, "length", line);
- oprintf (of, "); i%d++) {\n", loopcounter);
- indent += 2;
- switch (t->u.p->kind)
- {
- case TYPE_STRUCT:
- case TYPE_UNION:
- {
- char *newval;
-
- newval = xasprintf ("%s%s%s[i%d]", val, dot, f->name,
- loopcounter);
- write_gc_structure_fields (of, t->u.p, newval, val,
- f->opt, indent, &f->line,
- bitmap, param);
- free (newval);
- break;
- }
- case TYPE_POINTER:
- if (UNION_OR_STRUCT_P (t->u.p->u.p)
- || t->u.p->u.p->kind == TYPE_PARAM_STRUCT)
- {
- oprintf (of, "%*sgt_ggc_m_", indent, "");
- output_mangled_typename (of, t->u.p->u.p);
- oprintf (of, " (%s%s%s[i%d]);\n", val, dot, f->name,
- loopcounter);
- }
- else
- error_at_line (&f->line,
- "field `%s' is array of pointer to scalar",
- f->name);
- break;
- default:
- error_at_line (&f->line,
- "field `%s' is array of unimplemented type",
- f->name);
- break;
- }
- indent -= 2;
- oprintf (of, "%*s}\n", indent, "");
- indent -= 2;
- oprintf (of, "%*s}\n", indent, "");
- }
+ case TYPE_ARRAY:
+ {
+ int loopcounter = d->counter++;
+ const char *oldval = d->val;
+ char *newval;
+
+ /* If it's an array of scalars, we optimise by not generating
+ any code. */
+ if (t->u.a.p->kind == TYPE_SCALAR)
break;
+
+ oprintf (d->of, "%*s{\n", d->indent, "");
+ d->indent += 2;
+ oprintf (d->of, "%*ssize_t i%d;\n", d->indent, "", loopcounter);
+ oprintf (d->of, "%*sfor (i%d = 0; i%d < (size_t)(", d->indent, "",
+ loopcounter, loopcounter);
+ if (length)
+ output_escaped_param (d, length, "length");
+ else
+ oprintf (d->of, "%s", t->u.a.len);
+ oprintf (d->of, "); i%d++) {\n", loopcounter);
+ d->indent += 2;
+ d->val = newval = xasprintf ("%s[i%d]", oldval, loopcounter);
+ d->used_length = 1;
+ walk_type (t->u.a.p, d);
+ free (newval);
+ d->used_length = 0;
+ d->val = oldval;
+ d->indent -= 2;
+ oprintf (d->of, "%*s}\n", d->indent, "");
+ d->indent -= 2;
+ oprintf (d->of, "%*s}\n", d->indent, "");
+ }
+ break;
+
+ case TYPE_STRUCT:
+ case TYPE_UNION:
+ {
+ pair_p f;
+ const char *oldval = d->val;
+ const char *oldprevval1 = d->prev_val[1];
+ const char *oldprevval2 = d->prev_val[2];
+ const int union_p = t->kind == TYPE_UNION;
+ int seen_default_p = 0;
+ options_p o;
+
+ if (! t->u.s.line.file)
+ error_at_line (d->line, "incomplete structure `%s'", t->u.s.tag);
- case TYPE_ARRAY:
+ if ((d->bitmap & t->u.s.bitmap) != d->bitmap)
{
- int loopcounter = ++gc_counter;
- type_p ta;
- int i;
-
- if (! length &&
- (strcmp (t->u.a.len, "0") == 0
- || strcmp (t->u.a.len, "1") == 0))
- error_at_line (&f->line,
- "field `%s' is array of size %s",
- f->name, t->u.a.len);
-
- /* Arrays of scalars can be ignored. */
- for (ta = t; ta->kind == TYPE_ARRAY; ta = ta->u.a.p)
- ;
- if (ta->kind == TYPE_SCALAR
- || ta->kind == TYPE_STRING)
- break;
+ error_at_line (d->line,
+ "structure `%s' defined for mismatching languages",
+ t->u.s.tag);
+ error_at_line (&t->u.s.line, "one structure defined here");
+ }
- oprintf (of, "%*s{\n", indent, "");
- indent += 2;
+ /* Some things may also be defined in the structure's options. */
+ for (o = t->u.s.opt; o; o = o->next)
+ if (! desc && strcmp (o->name, "desc") == 0)
+ desc = (const char *)o->info;
- for (ta = t, i = 0; ta->kind == TYPE_ARRAY; ta = ta->u.a.p, i++)
+ d->prev_val[2] = oldval;
+ d->prev_val[1] = oldprevval2;
+ if (union_p)
+ {
+ if (desc == NULL)
{
- oprintf (of, "%*ssize_t i%d_%d;\n",
- indent, "", loopcounter, i);
- oprintf (of, "%*sconst size_t ilimit%d_%d = (",
- indent, "", loopcounter, i);
- if (i == 0 && length != NULL)
- output_escaped_param (of, length, val, prev_val,
- "length", line);
- else
- oprintf (of, "%s", ta->u.a.len);
- oprintf (of, ");\n");
+ error_at_line (d->line, "missing `desc' option for union `%s'",
+ t->u.s.tag);
+ desc = "1";
}
-
- for (ta = t, i = 0; ta->kind == TYPE_ARRAY; ta = ta->u.a.p, i++)
+ oprintf (d->of, "%*sswitch (", d->indent, "");
+ output_escaped_param (d, desc, "desc");
+ oprintf (d->of, ")\n");
+ d->indent += 2;
+ oprintf (d->of, "%*s{\n", d->indent, "");
+ }
+ for (f = t->u.s.fields; f; f = f->next)
+ {
+ options_p oo;
+ const char *dot = ".";
+ const char *tagid = NULL;
+ int skip_p = 0;
+ int default_p = 0;
+ int use_param_p = 0;
+ char *newval;
+
+ d->reorder_fn = NULL;
+ for (oo = f->opt; oo; oo = oo->next)
+ if (strcmp (oo->name, "dot") == 0)
+ dot = (const char *)oo->info;
+ else if (strcmp (oo->name, "tag") == 0)
+ tagid = (const char *)oo->info;
+ else if (strcmp (oo->name, "skip") == 0)
+ skip_p = 1;
+ else if (strcmp (oo->name, "default") == 0)
+ default_p = 1;
+ else if (strcmp (oo->name, "reorder") == 0)
+ d->reorder_fn = (const char *)oo->info;
+ else if (strncmp (oo->name, "use_param", 9) == 0
+ && (oo->name[9] == '\0' || ISDIGIT (oo->name[9])))
+ use_param_p = 1;
+
+ if (skip_p)
+ continue;
+
+ if (union_p && tagid)
{
- oprintf (of,
- "%*sfor (i%d_%d = 0; i%d_%d < ilimit%d_%d; i%d_%d++) {\n",
- indent, "", loopcounter, i, loopcounter, i,
- loopcounter, i, loopcounter, i);
- indent += 2;
+ oprintf (d->of, "%*scase %s:\n", d->indent, "", tagid);
+ d->indent += 2;
}
-
- if (ta->kind == TYPE_POINTER
- && (UNION_OR_STRUCT_P (ta->u.p)
- || ta->u.p->kind == TYPE_PARAM_STRUCT))
+ else if (union_p && default_p)
{
- oprintf (of, "%*sgt_ggc_m_", indent, "");
- output_mangled_typename (of, ta->u.p);
- oprintf (of, " (%s%s%s", val, dot, f->name);
- for (ta = t, i = 0;
- ta->kind == TYPE_ARRAY;
- ta = ta->u.a.p, i++)
- oprintf (of, "[i%d_%d]", loopcounter, i);
- oprintf (of, ");\n");
+ oprintf (d->of, "%*sdefault:\n", d->indent, "");
+ d->indent += 2;
+ seen_default_p = 1;
}
- else if (ta->kind == TYPE_STRUCT || ta->kind == TYPE_UNION)
+ else if (! union_p && (default_p || tagid))
+ error_at_line (d->line,
+ "can't use `%s' outside a union on field `%s'",
+ default_p ? "default" : "tag", f->name);
+ else if (union_p && ! (default_p || tagid)
+ && f->type->kind == TYPE_SCALAR)
{
- char *newval;
- int len;
-
- len = strlen (val) + strlen (f->name) + 2;
- for (ta = t; ta->kind == TYPE_ARRAY; ta = ta->u.a.p)
- len += sizeof ("[i_]") + 2*6;
-
- newval = xmalloc (len);
- sprintf (newval, "%s%s%s", val, dot, f->name);
- for (ta = t, i = 0;
- ta->kind == TYPE_ARRAY;
- ta = ta->u.a.p, i++)
- sprintf (newval + strlen (newval), "[i%d_%d]",
- loopcounter, i);
- write_gc_structure_fields (of, t->u.p, newval, val,
- f->opt, indent, &f->line, bitmap,
- param);
- free (newval);
+ fprintf (stderr,
+ "%s:%d: warning: field `%s' is missing `tag' or `default' option\n",
+ d->line->file, d->line->line, f->name);
+ continue;
}
- else if (ta->kind == TYPE_POINTER && ta->u.p->kind == TYPE_SCALAR
- && use_param_num != -1 && param == NULL)
- oprintf (of, "%*sabort();\n", indent, "");
- else
- error_at_line (&f->line,
- "field `%s' is array of unimplemented type",
+ else if (union_p && ! (default_p || tagid))
+ error_at_line (d->line,
+ "field `%s' is missing `tag' or `default' option",
f->name);
- for (ta = t, i = 0; ta->kind == TYPE_ARRAY; ta = ta->u.a.p, i++)
+
+ d->line = &f->line;
+ d->val = newval = xasprintf ("%s%s%s", oldval, dot, f->name);
+ d->opt = f->opt;
+
+ if (union_p && use_param_p && d->param == NULL)
+ oprintf (d->of, "%*sabort();\n", d->indent, "");
+ else
+ walk_type (f->type, d);
+
+ free (newval);
+
+ if (union_p)
{
- indent -= 2;
- oprintf (of, "%*s}\n", indent, "");
+ oprintf (d->of, "%*sbreak;\n", d->indent, "");
+ d->indent -= 2;
}
+ }
+ d->reorder_fn = NULL;
- indent -= 2;
- oprintf (of, "%*s}\n", indent, "");
- break;
+ d->val = oldval;
+ d->prev_val[1] = oldprevval1;
+ d->prev_val[2] = oldprevval2;
+
+ if (union_p && ! seen_default_p)
+ {
+ oprintf (d->of, "%*sdefault:\n", d->indent, "");
+ oprintf (d->of, "%*s break;\n", d->indent, "");
+ }
+ if (union_p)
+ {
+ oprintf (d->of, "%*s}\n", d->indent, "");
+ d->indent -= 2;
}
+ }
+ break;
- default:
- error_at_line (&f->line,
- "field `%s' is unimplemented type",
- f->name);
- break;
- }
+ case TYPE_LANG_STRUCT:
+ {
+ type_p nt;
+ for (nt = t->u.s.lang_struct; nt; nt = nt->next)
+ if ((d->bitmap & nt->u.s.bitmap) == d->bitmap)
+ break;
+ if (nt == NULL)
+ error_at_line (d->line, "structure `%s' differs between languages",
+ t->u.s.tag);
+ else
+ walk_type (nt, d);
+ }
+ break;
+
+ case TYPE_PARAM_STRUCT:
+ {
+ type_p *oldparam = d->param;
+
+ d->param = t->u.param_struct.param;
+ walk_type (t->u.param_struct.stru, d);
+ d->param = oldparam;
+ }
+ break;
- if (s->kind == TYPE_UNION)
- {
- oprintf (of, "%*sbreak;\n", indent, "");
- indent -= 2;
- }
+ default:
+ abort ();
}
- if (s->kind == TYPE_UNION)
+}
+
+/* process_field routine for marking routines. */
+
+static void
+write_types_process_field (f, d)
+ type_p f;
+ const struct walk_type_data *d;
+{
+ const struct write_types_data *wtd;
+ wtd = (const struct write_types_data *) d->cookie;
+
+ switch (f->kind)
{
- if (! seen_default)
+ case TYPE_POINTER:
+ oprintf (d->of, "%*s%s (%s", d->indent, "",
+ wtd->subfield_marker_routine, d->val);
+ if (wtd->param_prefix)
{
- oprintf (of, "%*sdefault:\n", indent, "");
- oprintf (of, "%*s break;\n", indent, "");
+ oprintf (d->of, ", %s", d->prev_val[3]);
+ if (d->orig_s)
+ {
+ oprintf (d->of, ", gt_%s_", wtd->param_prefix);
+ output_mangled_typename (d->of, d->orig_s);
+ }
+ else
+ oprintf (d->of, ", gt_%sa_%s", wtd->param_prefix, d->prev_val[0]);
}
- oprintf (of, "%*s}\n", indent, "");
- indent -= 2;
+ oprintf (d->of, ");\n");
+ if (d->reorder_fn && wtd->reorder_note_routine)
+ oprintf (d->of, "%*s%s (%s, %s, %s);\n", d->indent, "",
+ wtd->reorder_note_routine, d->val,
+ d->prev_val[3], d->reorder_fn);
+ break;
+
+ case TYPE_STRING:
+ if (wtd->param_prefix == NULL)
+ break;
+
+ case TYPE_STRUCT:
+ case TYPE_UNION:
+ case TYPE_LANG_STRUCT:
+ case TYPE_PARAM_STRUCT:
+ oprintf (d->of, "%*sgt_%s_", d->indent, "", wtd->prefix);
+ output_mangled_typename (d->of, f);
+ oprintf (d->of, " (%s);\n", d->val);
+ if (d->reorder_fn && wtd->reorder_note_routine)
+ oprintf (d->of, "%*s%s (%s, %s, %s);\n", d->indent, "",
+ wtd->reorder_note_routine, d->val, d->val,
+ d->reorder_fn);
+ break;
+
+ case TYPE_SCALAR:
+ break;
+
+ default:
+ abort ();
}
}
-/* Write out a marker routine for S. PARAM is the parameter from an
- enclosing PARAM_IS option. */
+/* For S, a structure that's part of ORIG_S, and using parameters
+ PARAM, write out a routine that:
+ - Takes a parameter, a void * but actually of type *S
+ - If SEEN_ROUTINE returns nonzero, calls write_types_process_field on each
+ field of S or its substructures and (in some cases) things
+ that are pointed to by S.
+*/
static void
-write_gc_marker_routine_for_structure (orig_s, s, param)
+write_func_for_structure (orig_s, s, param, wtd)
type_p orig_s;
type_p s;
type_p * param;
+ const struct write_types_data *wtd;
{
- outf_p f;
const char *fn = s->u.s.line.file;
int i;
const char *chain_next = NULL;
const char *chain_prev = NULL;
options_p opt;
+ struct walk_type_data d;
/* This is a hack, and not the good kind either. */
for (i = NUM_PARAM - 1; i >= 0; i--)
@@ -1893,7 +1961,8 @@ write_gc_marker_routine_for_structure (orig_s, s, param)
&& UNION_OR_STRUCT_P (param[i]->u.p))
fn = param[i]->u.p->u.s.line.file;
- f = get_output_file_with_visibility (fn);
+ memset (&d, 0, sizeof (d));
+ d.of = get_output_file_with_visibility (fn);
for (opt = s->u.s.opt; opt; opt = opt->next)
if (strcmp (opt->name, "chain_next") == 0)
@@ -1904,80 +1973,113 @@ write_gc_marker_routine_for_structure (orig_s, s, param)
if (chain_prev != NULL && chain_next == NULL)
error_at_line (&s->u.s.line, "chain_prev without chain_next");
- oprintf (f, "\n");
- oprintf (f, "void\n");
+ d.process_field = write_types_process_field;
+ d.cookie = wtd;
+ d.orig_s = orig_s;
+ d.opt = s->u.s.opt;
+ d.line = &s->u.s.line;
+ d.bitmap = s->u.s.bitmap;
+ d.param = param;
+ d.prev_val[0] = "*x";
+ d.prev_val[1] = "not valid postage"; /* guarantee an error */
+ d.prev_val[3] = "x";
+ d.val = "(*x)";
+
+ oprintf (d.of, "\n");
+ oprintf (d.of, "void\n");
if (param == NULL)
- oprintf (f, "gt_ggc_mx_%s", s->u.s.tag);
+ oprintf (d.of, "gt_%sx_%s", wtd->prefix, orig_s->u.s.tag);
else
{
- oprintf (f, "gt_ggc_m_");
- output_mangled_typename (f, orig_s);
+ oprintf (d.of, "gt_%s_", wtd->prefix);
+ output_mangled_typename (d.of, orig_s);
}
- oprintf (f, " (x_p)\n");
- oprintf (f, " void *x_p;\n");
- oprintf (f, "{\n");
- oprintf (f, " %s %s * %sx = (%s %s *)x_p;\n",
+ oprintf (d.of, " (x_p)\n");
+ oprintf (d.of, " void *x_p;\n");
+ oprintf (d.of, "{\n");
+ oprintf (d.of, " %s %s * %sx = (%s %s *)x_p;\n",
s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag,
chain_next == NULL ? "const " : "",
s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
if (chain_next != NULL)
- oprintf (f, " %s %s * xlimit = x;\n",
+ oprintf (d.of, " %s %s * xlimit = x;\n",
s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
if (chain_next == NULL)
- oprintf (f, " if (ggc_test_and_set_mark (x))\n");
+ {
+ oprintf (d.of, " if (%s (x", wtd->marker_routine);
+ if (wtd->param_prefix)
+ {
+ oprintf (d.of, ", x, gt_%s_", wtd->param_prefix);
+ output_mangled_typename (d.of, orig_s);
+ }
+ oprintf (d.of, "))\n");
+ }
else
{
- oprintf (f, " while (ggc_test_and_set_mark (xlimit))\n");
- oprintf (f, " xlimit = (");
- output_escaped_param (f, chain_next, "*xlimit", "*xlimit",
- "chain_next", &s->u.s.line);
- oprintf (f, ");\n");
+ oprintf (d.of, " while (%s (xlimit", wtd->marker_routine);
+ if (wtd->param_prefix)
+ {
+ oprintf (d.of, ", xlimit, gt_%s_", wtd->param_prefix);
+ output_mangled_typename (d.of, orig_s);
+ }
+ oprintf (d.of, "))\n");
+ oprintf (d.of, " xlimit = (");
+ d.prev_val[2] = "*xlimit";
+ output_escaped_param (&d, chain_next, "chain_next");
+ oprintf (d.of, ");\n");
if (chain_prev != NULL)
{
- oprintf (f, " if (x != xlimit)\n");
- oprintf (f, " for (;;)\n");
- oprintf (f, " {\n");
- oprintf (f, " %s %s * const xprev = (",
+ oprintf (d.of, " if (x != xlimit)\n");
+ oprintf (d.of, " for (;;)\n");
+ oprintf (d.of, " {\n");
+ oprintf (d.of, " %s %s * const xprev = (",
s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
- output_escaped_param (f, chain_prev, "*x", "*x",
- "chain_prev", &s->u.s.line);
- oprintf (f, ");\n");
- oprintf (f, " if (xprev == NULL) break;\n");
- oprintf (f, " x = xprev;\n");
- oprintf (f, " ggc_set_mark (xprev);\n");
- oprintf (f, " }\n");
+
+ d.prev_val[2] = "*x";
+ output_escaped_param (&d, chain_prev, "chain_prev");
+ oprintf (d.of, ");\n");
+ oprintf (d.of, " if (xprev == NULL) break;\n");
+ oprintf (d.of, " x = xprev;\n");
+ oprintf (d.of, " (void) %s (xprev",
+ wtd->marker_routine);
+ if (wtd->param_prefix)
+ {
+ oprintf (d.of, ", xprev, gt_%s_", wtd->param_prefix);
+ output_mangled_typename (d.of, orig_s);
+ }
+ oprintf (d.of, ");\n");
+ oprintf (d.of, " }\n");
}
- oprintf (f, " while (x != xlimit)\n");
+ oprintf (d.of, " while (x != xlimit)\n");
}
- oprintf (f, " {\n");
+ oprintf (d.of, " {\n");
- gc_counter = 0;
- write_gc_structure_fields (f, s, "(*x)", "not valid postage",
- s->u.s.opt, 6, &s->u.s.line, s->u.s.bitmap,
- param);
+ d.prev_val[2] = "*x";
+ d.indent = 6;
+ walk_type (s, &d);
if (chain_next != NULL)
{
- oprintf (f, " x = (");
- output_escaped_param (f, chain_next, "*x", "*x",
- "chain_next", &s->u.s.line);
- oprintf (f, ");\n");
+ oprintf (d.of, " x = (");
+ output_escaped_param (&d, chain_next, "chain_next");
+ oprintf (d.of, ");\n");
}
- oprintf (f, " }\n");
- oprintf (f, "}\n");
+ oprintf (d.of, " }\n");
+ oprintf (d.of, "}\n");
}
/* Write out marker routines for STRUCTURES and PARAM_STRUCTS. */
static void
-write_gc_types (structures, param_structs)
+write_types (structures, param_structs, wtd)
type_p structures;
type_p param_structs;
+ const struct write_types_data *wtd;
{
type_p s;
- oprintf (header_file, "\n/* GC marker procedures. */\n");
+ oprintf (header_file, "\n/* %s*/\n", wtd->comment);
for (s = structures; s; s = s->next)
if (s->gc_used == GC_POINTED_TO
|| s->gc_used == GC_MAYBE_POINTED_TO)
@@ -1988,11 +2090,12 @@ write_gc_types (structures, param_structs)
&& s->u.s.line.file == NULL)
continue;
- oprintf (header_file, "#define gt_ggc_m_");
+ oprintf (header_file, "#define gt_%s_", wtd->prefix);
output_mangled_typename (header_file, s);
oprintf (header_file, "(X) do { \\\n");
oprintf (header_file,
- " if (X != NULL) gt_ggc_mx_%s (X);\\\n", s->u.s.tag);
+ " if (X != NULL) gt_%sx_%s (X);\\\n", wtd->prefix,
+ s->u.s.tag);
oprintf (header_file,
" } while (0)\n");
@@ -2004,8 +2107,8 @@ write_gc_types (structures, param_structs)
|| t->kind == TYPE_UNION
|| t->kind == TYPE_LANG_STRUCT)
oprintf (header_file,
- "#define gt_ggc_mx_%s gt_ggc_mx_%s\n",
- s->u.s.tag, t->u.s.tag);
+ "#define gt_%sx_%s gt_%sx_%s\n",
+ wtd->prefix, s->u.s.tag, wtd->prefix, t->u.s.tag);
else
error_at_line (&s->u.s.line,
"structure alias is not a structure");
@@ -2016,8 +2119,8 @@ write_gc_types (structures, param_structs)
/* Declare the marker procedure only once. */
oprintf (header_file,
- "extern void gt_ggc_mx_%s PARAMS ((void *));\n",
- s->u.s.tag);
+ "extern void gt_%sx_%s PARAMS ((void *));\n",
+ wtd->prefix, s->u.s.tag);
if (s->u.s.line.file == NULL)
{
@@ -2030,10 +2133,10 @@ write_gc_types (structures, param_structs)
{
type_p ss;
for (ss = s->u.s.lang_struct; ss; ss = ss->next)
- write_gc_marker_routine_for_structure (s, ss, NULL);
+ write_func_for_structure (s, ss, NULL, wtd);
}
else
- write_gc_marker_routine_for_structure (s, s, NULL);
+ write_func_for_structure (s, s, NULL, wtd);
}
for (s = param_structs; s; s = s->next)
@@ -2043,7 +2146,7 @@ write_gc_types (structures, param_structs)
type_p stru = s->u.param_struct.stru;
/* Declare the marker procedure. */
- oprintf (header_file, "extern void gt_ggc_m_");
+ oprintf (header_file, "extern void gt_%s_", wtd->prefix);
output_mangled_typename (header_file, s);
oprintf (header_file, " PARAMS ((void *));\n");
@@ -2058,10 +2161,193 @@ write_gc_types (structures, param_structs)
{
type_p ss;
for (ss = stru->u.s.lang_struct; ss; ss = ss->next)
- write_gc_marker_routine_for_structure (s, ss, param);
+ write_func_for_structure (s, ss, param, wtd);
+ }
+ else
+ write_func_for_structure (s, stru, param, wtd);
+ }
+}
+
+static const struct write_types_data ggc_wtd =
+{
+ "ggc_m", NULL, "ggc_mark", "ggc_test_and_set_mark", NULL,
+ "GC marker procedures. "
+};
+
+static const struct write_types_data pch_wtd =
+{
+ "pch_n", "pch_p", "gt_pch_note_object", "gt_pch_note_object",
+ "gt_pch_note_reorder",
+ "PCH type-walking procedures. "
+};
+
+/* Write out the local pointer-walking routines. */
+
+/* process_field routine for local pointer-walking. */
+
+static void
+write_types_local_process_field (f, d)
+ type_p f;
+ const struct walk_type_data *d;
+{
+ switch (f->kind)
+ {
+ case TYPE_POINTER:
+ case TYPE_STRUCT:
+ case TYPE_UNION:
+ case TYPE_LANG_STRUCT:
+ case TYPE_PARAM_STRUCT:
+ case TYPE_STRING:
+ oprintf (d->of, "%*sif ((void *)(%s) == this_obj)\n", d->indent, "",
+ d->prev_val[3]);
+ oprintf (d->of, "%*s op (&(%s), cookie);\n", d->indent, "", d->val);
+ break;
+
+ case TYPE_SCALAR:
+ break;
+
+ default:
+ abort ();
+ }
+}
+
+/* For S, a structure that's part of ORIG_S, and using parameters
+ PARAM, write out a routine that:
+ - Is of type gt_note_pointers
+ - If calls PROCESS_FIELD on each field of S or its substructures.
+*/
+
+static void
+write_local_func_for_structure (orig_s, s, param)
+ type_p orig_s;
+ type_p s;
+ type_p * param;
+{
+ const char *fn = s->u.s.line.file;
+ int i;
+ struct walk_type_data d;
+
+ /* This is a hack, and not the good kind either. */
+ for (i = NUM_PARAM - 1; i >= 0; i--)
+ if (param && param[i] && param[i]->kind == TYPE_POINTER
+ && UNION_OR_STRUCT_P (param[i]->u.p))
+ fn = param[i]->u.p->u.s.line.file;
+
+ memset (&d, 0, sizeof (d));
+ d.of = get_output_file_with_visibility (fn);
+
+ d.process_field = write_types_local_process_field;
+ d.opt = s->u.s.opt;
+ d.line = &s->u.s.line;
+ d.bitmap = s->u.s.bitmap;
+ d.param = param;
+ d.prev_val[0] = d.prev_val[2] = "*x";
+ d.prev_val[1] = "not valid postage"; /* guarantee an error */
+ d.prev_val[3] = "x";
+ d.val = "(*x)";
+
+ oprintf (d.of, "\n");
+ oprintf (d.of, "void\n");
+ oprintf (d.of, "gt_pch_p_");
+ output_mangled_typename (d.of, orig_s);
+ oprintf (d.of, " (this_obj, x_p, op, cookie)\n");
+ oprintf (d.of, " void *this_obj ATTRIBUTE_UNUSED;\n");
+ oprintf (d.of, " void *x_p;\n");
+ oprintf (d.of, " gt_pointer_operator op ATTRIBUTE_UNUSED;\n");
+ oprintf (d.of, " void *cookie ATTRIBUTE_UNUSED;\n");
+ oprintf (d.of, "{\n");
+ oprintf (d.of, " %s %s * const x ATTRIBUTE_UNUSED = (%s %s *)x_p;\n",
+ s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag,
+ s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
+ d.indent = 2;
+ walk_type (s, &d);
+ oprintf (d.of, "}\n");
+}
+
+/* Write out local marker routines for STRUCTURES and PARAM_STRUCTS. */
+
+static void
+write_local (structures, param_structs)
+ type_p structures;
+ type_p param_structs;
+{
+ type_p s;
+
+ oprintf (header_file, "\n/* Local pointer-walking routines. */\n");
+ for (s = structures; s; s = s->next)
+ if (s->gc_used == GC_POINTED_TO
+ || s->gc_used == GC_MAYBE_POINTED_TO)
+ {
+ options_p opt;
+
+ if (s->u.s.line.file == NULL)
+ continue;
+
+ for (opt = s->u.s.opt; opt; opt = opt->next)
+ if (strcmp (opt->name, "ptr_alias") == 0)
+ {
+ type_p t = (type_p) opt->info;
+ if (t->kind == TYPE_STRUCT
+ || t->kind == TYPE_UNION
+ || t->kind == TYPE_LANG_STRUCT)
+ {
+ oprintf (header_file, "#define gt_pch_p_");
+ output_mangled_typename (header_file, s);
+ oprintf (header_file, " gt_pch_p_");
+ output_mangled_typename (header_file, t);
+ oprintf (header_file, "\n");
+ }
+ else
+ error_at_line (&s->u.s.line,
+ "structure alias is not a structure");
+ break;
+ }
+ if (opt)
+ continue;
+
+ /* Declare the marker procedure only once. */
+ oprintf (header_file, "extern void gt_pch_p_");
+ output_mangled_typename (header_file, s);
+ oprintf (header_file,
+ "\n PARAMS ((void *, void *, gt_pointer_operator, void *));\n");
+
+ if (s->kind == TYPE_LANG_STRUCT)
+ {
+ type_p ss;
+ for (ss = s->u.s.lang_struct; ss; ss = ss->next)
+ write_local_func_for_structure (s, ss, NULL);
+ }
+ else
+ write_local_func_for_structure (s, s, NULL);
+ }
+
+ for (s = param_structs; s; s = s->next)
+ if (s->gc_used == GC_POINTED_TO)
+ {
+ type_p * param = s->u.param_struct.param;
+ type_p stru = s->u.param_struct.stru;
+
+ /* Declare the marker procedure. */
+ oprintf (header_file, "extern void gt_pch_p_");
+ output_mangled_typename (header_file, s);
+ oprintf (header_file,
+ "\n PARAMS ((void *, void *, gt_pointer_operator, void *));\n");
+
+ if (stru->u.s.line.file == NULL)
+ {
+ fprintf (stderr, "warning: structure `%s' used but not defined\n",
+ s->u.s.tag);
+ continue;
+ }
+
+ if (stru->kind == TYPE_LANG_STRUCT)
+ {
+ type_p ss;
+ for (ss = stru->u.s.lang_struct; ss; ss = ss->next)
+ write_local_func_for_structure (s, ss, param);
}
else
- write_gc_marker_routine_for_structure (s, stru, param);
+ write_local_func_for_structure (s, stru, param);
}
}
@@ -2099,6 +2385,25 @@ write_enum_defn (structures, param_structs)
oprintf (header_file, "};\n");
}
+/* Might T contain any non-pointer elements? */
+
+static int
+contains_scalar_p (t)
+ type_p t;
+{
+ switch (t->kind)
+ {
+ case TYPE_STRING:
+ case TYPE_POINTER:
+ return 0;
+ case TYPE_ARRAY:
+ return contains_scalar_p (t->u.a.p);
+ default:
+ /* Could also check for structures that have no non-pointer
+ fields, but there aren't enough of those to worry about. */
+ return 1;
+ }
+}
/* Mangle FN and print it to F. */
@@ -2128,7 +2433,6 @@ finish_root_table (flp, pfx, lastname, tname, name)
const char *name;
{
struct flist *fli2;
- unsigned started_bitmap = 0;
for (fli2 = flp; fli2; fli2 = fli2->next)
if (fli2->started_p)
@@ -2147,12 +2451,21 @@ finish_root_table (flp, pfx, lastname, tname, name)
if (bitmap & 1)
{
oprintf (base_files[fnum],
- "extern const struct %s gt_ggc_%s_",
+ "extern const struct %s gt_%s_",
tname, pfx);
put_mangled_filename (base_files[fnum], fli2->name);
oprintf (base_files[fnum], "[];\n");
}
}
+
+ {
+ size_t fnum;
+ for (fnum = 0; fnum < NUM_BASE_FILES; fnum++)
+ oprintf (base_files [fnum],
+ "const struct %s * const %s[] = {\n",
+ tname, name);
+ }
+
for (fli2 = flp; fli2; fli2 = fli2->next)
if (fli2->started_p)
@@ -2165,29 +2478,19 @@ finish_root_table (flp, pfx, lastname, tname, name)
for (fnum = 0; bitmap != 0; fnum++, bitmap >>= 1)
if (bitmap & 1)
{
- if (! (started_bitmap & (1 << fnum)))
- {
- oprintf (base_files [fnum],
- "const struct %s * const %s[] = {\n",
- tname, name);
- started_bitmap |= 1 << fnum;
- }
- oprintf (base_files[fnum], " gt_ggc_%s_", pfx);
+ oprintf (base_files[fnum], " gt_%s_", pfx);
put_mangled_filename (base_files[fnum], fli2->name);
oprintf (base_files[fnum], ",\n");
}
}
{
- unsigned bitmap;
- int fnum;
-
- for (bitmap = started_bitmap, fnum = 0; bitmap != 0; fnum++, bitmap >>= 1)
- if (bitmap & 1)
- {
- oprintf (base_files[fnum], " NULL\n");
- oprintf (base_files[fnum], "};\n");
- }
+ size_t fnum;
+ for (fnum = 0; fnum < NUM_BASE_FILES; fnum++)
+ {
+ oprintf (base_files[fnum], " NULL\n");
+ oprintf (base_files[fnum], "};\n");
+ }
}
}
@@ -2197,7 +2500,7 @@ finish_root_table (flp, pfx, lastname, tname, name)
is nonzero iff we are building the root table for hash table caches. */
static void
-write_gc_root (f, v, type, name, has_length, line, if_marked)
+write_root (f, v, type, name, has_length, line, if_marked)
outf_p f;
pair_p v;
type_p type;
@@ -2257,8 +2560,8 @@ write_gc_root (f, v, type, name, has_length, line, if_marked)
char *newname;
newname = xasprintf ("%s.%s.%s",
name, fld->name, validf->name);
- write_gc_root (f, v, validf->type, newname, 0, line,
- if_marked);
+ write_root (f, v, validf->type, newname, 0, line,
+ if_marked);
free (newname);
}
}
@@ -2270,7 +2573,7 @@ write_gc_root (f, v, type, name, has_length, line, if_marked)
{
char *newname;
newname = xasprintf ("%s.%s", name, fld->name);
- write_gc_root (f, v, fld->type, newname, 0, line, if_marked);
+ write_root (f, v, fld->type, newname, 0, line, if_marked);
free (newname);
}
}
@@ -2281,7 +2584,7 @@ write_gc_root (f, v, type, name, has_length, line, if_marked)
{
char *newname;
newname = xasprintf ("%s[0]", name);
- write_gc_root (f, v, type->u.a.p, newname, has_length, line, if_marked);
+ write_root (f, v, type->u.a.p, newname, has_length, line, if_marked);
free (newname);
}
break;
@@ -2309,17 +2612,21 @@ write_gc_root (f, v, type, name, has_length, line, if_marked)
if (! has_length && UNION_OR_STRUCT_P (tp))
{
- oprintf (f, " &gt_ggc_mx_%s\n", tp->u.s.tag);
+ oprintf (f, " &gt_ggc_mx_%s,\n", tp->u.s.tag);
+ oprintf (f, " &gt_pch_nx_%s", tp->u.s.tag);
}
else if (! has_length && tp->kind == TYPE_PARAM_STRUCT)
{
oprintf (f, " &gt_ggc_m_");
output_mangled_typename (f, tp);
+ oprintf (f, ",\n &gt_pch_n_");
+ output_mangled_typename (f, tp);
}
else if (has_length
&& (tp->kind == TYPE_POINTER || UNION_OR_STRUCT_P (tp)))
{
- oprintf (f, " &gt_ggc_ma_%s", name);
+ oprintf (f, " &gt_ggc_ma_%s,\n", name);
+ oprintf (f, " &gt_pch_na_%s", name);
}
else
{
@@ -2333,8 +2640,19 @@ write_gc_root (f, v, type, name, has_length, line, if_marked)
}
break;
- case TYPE_SCALAR:
case TYPE_STRING:
+ {
+ oprintf (f, " {\n");
+ oprintf (f, " &%s,\n", name);
+ oprintf (f, " 1, \n");
+ oprintf (f, " sizeof (%s),\n", v->name);
+ oprintf (f, " &gt_ggc_m_S,\n");
+ oprintf (f, " &gt_pch_n_S\n");
+ oprintf (f, " },\n");
+ }
+ break;
+
+ case TYPE_SCALAR:
break;
default:
@@ -2344,10 +2662,64 @@ write_gc_root (f, v, type, name, has_length, line, if_marked)
}
}
+/* This generates a routine to walk an array. */
+
+static void
+write_array (f, v, wtd)
+ outf_p f;
+ pair_p v;
+ const struct write_types_data *wtd;
+{
+ struct walk_type_data d;
+ char *prevval3;
+
+ memset (&d, 0, sizeof (d));
+ d.of = f;
+ d.cookie = wtd;
+ d.indent = 2;
+ d.line = &v->line;
+ d.opt = v->opt;
+ d.bitmap = get_base_file_bitmap (v->line.file);
+ d.param = NULL;
+
+ d.prev_val[3] = prevval3 = xasprintf ("&%s", v->name);
+
+ if (wtd->param_prefix)
+ {
+ oprintf (f, "static void gt_%sa_%s\n", wtd->param_prefix, v->name);
+ oprintf (f,
+ " PARAMS ((void *, void *, gt_pointer_operator, void *));\n");
+ oprintf (f, "static void gt_%sa_%s (this_obj, x_p, op, cookie)\n",
+ wtd->param_prefix, v->name);
+ oprintf (d.of, " void *this_obj ATTRIBUTE_UNUSED;\n");
+ oprintf (d.of, " void *x_p ATTRIBUTE_UNUSED;\n");
+ oprintf (d.of, " gt_pointer_operator op ATTRIBUTE_UNUSED;\n");
+ oprintf (d.of, " void *cookie ATTRIBUTE_UNUSED;\n");
+ oprintf (d.of, "{\n");
+ d.prev_val[0] = d.prev_val[1] = d.prev_val[2] = d.val = v->name;
+ d.process_field = write_types_local_process_field;
+ walk_type (v->type, &d);
+ oprintf (f, "}\n\n");
+ }
+
+ d.opt = v->opt;
+ oprintf (f, "static void gt_%sa_%s PARAMS ((void *));\n",
+ wtd->prefix, v->name);
+ oprintf (f, "static void\ngt_%sa_%s (x_p)\n",
+ wtd->prefix, v->name);
+ oprintf (f, " void *x_p ATTRIBUTE_UNUSED;\n");
+ oprintf (f, "{\n");
+ d.prev_val[0] = d.prev_val[1] = d.prev_val[2] = d.val = v->name;
+ d.process_field = write_types_process_field;
+ walk_type (v->type, &d);
+ free (prevval3);
+ oprintf (f, "}\n\n");
+}
+
/* Output a table describing the locations and types of VARIABLES. */
static void
-write_gc_roots (variables)
+write_roots (variables)
pair_p variables;
{
pair_p v;
@@ -2400,52 +2772,8 @@ write_gc_roots (variables)
&& (v->type->u.p->kind == TYPE_POINTER
|| v->type->u.p->kind == TYPE_STRUCT))
{
- oprintf (f, "static void gt_ggc_ma_%s PARAMS ((void *));\n",
- v->name);
- oprintf (f, "static void\ngt_ggc_ma_%s (x_p)\n void *x_p;\n",
- v->name);
- oprintf (f, "{\n");
- oprintf (f, " size_t i;\n");
-
- if (v->type->u.p->kind == TYPE_POINTER)
- {
- type_p s = v->type->u.p->u.p;
-
- oprintf (f, " %s %s ** const x = (%s %s **)x_p;\n",
- s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag,
- s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
- oprintf (f, " if (ggc_test_and_set_mark (x))\n");
- oprintf (f, " for (i = 0; i < (%s); i++)\n", length);
- if (! UNION_OR_STRUCT_P (s)
- && ! s->kind == TYPE_PARAM_STRUCT)
- {
- error_at_line (&v->line,
- "global `%s' has unsupported ** type",
- v->name);
- continue;
- }
-
- oprintf (f, " gt_ggc_m_");
- output_mangled_typename (f, s);
- oprintf (f, " (x[i]);\n");
- }
- else
- {
- type_p s = v->type->u.p;
-
- oprintf (f, " %s %s * const x = (%s %s *)x_p;\n",
- s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag,
- s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
- oprintf (f, " if (ggc_test_and_set_mark (x))\n");
- oprintf (f, " for (i = 0; i < (%s); i++)\n", length);
- oprintf (f, " {\n");
- write_gc_structure_fields (f, s, "x[i]", "x[i]",
- v->opt, 8, &v->line, s->u.s.bitmap,
- NULL);
- oprintf (f, " }\n");
- }
-
- oprintf (f, "}\n\n");
+ write_array (f, v, &ggc_wtd);
+ write_array (f, v, &pch_wtd);
}
}
@@ -2479,10 +2807,10 @@ write_gc_roots (variables)
oprintf (f, "[] = {\n");
}
- write_gc_root (f, v, v->type, v->name, length_p, &v->line, NULL);
+ write_root (f, v, v->type, v->name, length_p, &v->line, NULL);
}
- finish_root_table (flp, "r", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
+ finish_root_table (flp, "ggc_r", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
"gt_ggc_rtab");
for (v = variables; v; v = v->next)
@@ -2513,11 +2841,11 @@ write_gc_roots (variables)
oprintf (f, "[] = {\n");
}
- oprintf (f, " { &%s, 1, sizeof (%s), NULL },\n",
+ oprintf (f, " { &%s, 1, sizeof (%s), NULL, NULL },\n",
v->name, v->name);
}
- finish_root_table (flp, "rd", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
+ finish_root_table (flp, "ggc_rd", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
"gt_ggc_deletable_rtab");
for (v = variables; v; v = v->next)
@@ -2557,12 +2885,84 @@ write_gc_roots (variables)
oprintf (f, "[] = {\n");
}
- write_gc_root (f, v, v->type->u.p->u.param_struct.param[0],
+ write_root (f, v, v->type->u.p->u.param_struct.param[0],
v->name, length_p, &v->line, if_marked);
}
- finish_root_table (flp, "rc", "LAST_GGC_CACHE_TAB", "ggc_cache_tab",
+ finish_root_table (flp, "ggc_rc", "LAST_GGC_CACHE_TAB", "ggc_cache_tab",
"gt_ggc_cache_rtab");
+
+ for (v = variables; v; v = v->next)
+ {
+ outf_p f = get_output_file_with_visibility (v->line.file);
+ struct flist *fli;
+ int length_p = 0;
+ int if_marked_p = 0;
+ options_p o;
+
+ for (o = v->opt; o; o = o->next)
+ if (strcmp (o->name, "length") == 0)
+ length_p = 1;
+ else if (strcmp (o->name, "if_marked") == 0)
+ if_marked_p = 1;
+
+ if (! if_marked_p)
+ continue;
+
+ for (fli = flp; fli; fli = fli->next)
+ if (fli->f == f)
+ break;
+ if (! fli->started_p)
+ {
+ fli->started_p = 1;
+
+ oprintf (f, "const struct ggc_root_tab gt_pch_rc_");
+ put_mangled_filename (f, v->line.file);
+ oprintf (f, "[] = {\n");
+ }
+
+ write_root (f, v, v->type, v->name, length_p, &v->line, NULL);
+ }
+
+ finish_root_table (flp, "pch_rc", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
+ "gt_pch_cache_rtab");
+
+ for (v = variables; v; v = v->next)
+ {
+ outf_p f = get_output_file_with_visibility (v->line.file);
+ struct flist *fli;
+ int skip_p = 0;
+ options_p o;
+
+ for (o = v->opt; o; o = o->next)
+ if (strcmp (o->name, "deletable") == 0
+ || strcmp (o->name, "if_marked") == 0)
+ skip_p = 1;
+
+ if (skip_p)
+ continue;
+
+ if (! contains_scalar_p (v->type))
+ continue;
+
+ for (fli = flp; fli; fli = fli->next)
+ if (fli->f == f)
+ break;
+ if (! fli->started_p)
+ {
+ fli->started_p = 1;
+
+ oprintf (f, "const struct ggc_root_tab gt_pch_rs_");
+ put_mangled_filename (f, v->line.file);
+ oprintf (f, "[] = {\n");
+ }
+
+ oprintf (f, " { &%s, 1, sizeof (%s), NULL, NULL },\n",
+ v->name, v->name);
+ }
+
+ finish_root_table (flp, "pch_rs", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
+ "gt_pch_scalar_rtab");
}
@@ -2616,8 +3016,10 @@ main(argc, argv)
open_base_files ();
write_enum_defn (structures, param_structs);
- write_gc_types (structures, param_structs);
- write_gc_roots (variables);
+ write_types (structures, param_structs, &ggc_wtd);
+ write_types (structures, param_structs, &pch_wtd);
+ write_local (structures, param_structs);
+ write_roots (variables);
write_rtx_next ();
close_output_files ();
diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c
index f353617f4f7..ed6d3b45a85 100644
--- a/gcc/ggc-common.c
+++ b/gcc/ggc-common.c
@@ -24,14 +24,14 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tm.h"
-#include "rtl.h"
-#include "tree.h"
-#include "tm_p.h"
#include "hashtab.h"
-#include "varray.h"
#include "ggc.h"
-#include "langhooks.h"
+#include "toplev.h"
+
+#ifdef HAVE_MMAP_FILE
+# include <sys/mman.h>
+#endif
+
#ifdef ENABLE_VALGRIND_CHECKING
#include <valgrind.h>
#else
@@ -42,46 +42,20 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
/* Statistics about the allocation. */
static ggc_statistics *ggc_stats;
+struct traversal_state;
+
static int ggc_htab_delete PARAMS ((void **, void *));
+static hashval_t saving_htab_hash PARAMS ((const PTR));
+static int saving_htab_eq PARAMS ((const PTR, const PTR));
+static int call_count PARAMS ((void **, void *));
+static int call_alloc PARAMS ((void **, void *));
+static int compare_ptr_data PARAMS ((const void *, const void *));
+static void relocate_ptrs PARAMS ((void *, void *));
+static void write_pch_globals PARAMS ((const struct ggc_root_tab * const *tab,
+ struct traversal_state *state));
/* Maintain global roots that are preserved during GC. */
-/* Global roots that are preserved during calls to gc. */
-
-struct ggc_root
-{
- struct ggc_root *next;
- void *base;
- int nelt;
- int size;
- void (*cb) PARAMS ((void *));
-};
-
-static struct ggc_root *roots;
-
-/* Add BASE as a new garbage collection root. It is an array of
- length NELT with each element SIZE bytes long. CB is a
- function that will be called with a pointer to each element
- of the array; it is the intention that CB call the appropriate
- routine to mark gc-able memory for that element. */
-
-void
-ggc_add_root (base, nelt, size, cb)
- void *base;
- int nelt, size;
- void (*cb) PARAMS ((void *));
-{
- struct ggc_root *x = (struct ggc_root *) xmalloc (sizeof (*x));
-
- x->next = roots;
- x->base = base;
- x->nelt = nelt;
- x->size = size;
- x->cb = cb;
-
- roots = x;
-}
-
/* Process a slot of an htab by deleting it if it has not been marked. */
static int
@@ -104,7 +78,6 @@ ggc_htab_delete (slot, info)
void
ggc_mark_roots ()
{
- struct ggc_root *x;
const struct ggc_root_tab *const *rt;
const struct ggc_root_tab *rti;
const struct ggc_cache_tab *const *ct;
@@ -120,23 +93,18 @@ ggc_mark_roots ()
for (i = 0; i < rti->nelt; i++)
(*rti->cb)(*(void **)((char *)rti->base + rti->stride * i));
- for (x = roots; x != NULL; x = x->next)
- {
- char *elt = x->base;
- int s = x->size, n = x->nelt;
- void (*cb) PARAMS ((void *)) = x->cb;
- int i;
-
- for (i = 0; i < n; ++i, elt += s)
- (*cb)(elt);
- }
+ ggc_mark_stringpool ();
/* Now scan all hash tables that have objects which are to be deleted if
they are not already marked. */
for (ct = gt_ggc_cache_rtab; *ct; ct++)
for (cti = *ct; cti->base != NULL; cti++)
if (*cti->base)
- htab_traverse (*cti->base, ggc_htab_delete, (PTR) cti);
+ {
+ ggc_set_mark (*cti->base);
+ htab_traverse (*cti->base, ggc_htab_delete, (PTR) cti);
+ ggc_set_mark ((*cti->base)->entries);
+ }
}
/* Allocate a block of memory, then clear it. */
@@ -204,6 +172,26 @@ ggc_calloc (s1, s2)
return ggc_alloc_cleared (s1 * s2);
}
+/* These are for splay_tree_new_ggc. */
+PTR
+ggc_splay_alloc (sz, nl)
+ int sz;
+ PTR nl;
+{
+ if (nl != NULL)
+ abort ();
+ return ggc_alloc (sz);
+}
+
+void
+ggc_splay_dont_free (x, nl)
+ PTR x ATTRIBUTE_UNUSED;
+ PTR nl;
+{
+ if (nl != NULL)
+ abort ();
+}
+
/* Print statistics that are independent of the collector in use. */
#define SCALE(x) ((unsigned long) ((x) < 1024*10 \
? (x) \
@@ -214,11 +202,9 @@ ggc_calloc (s1, s2)
void
ggc_print_common_statistics (stream, stats)
- FILE *stream;
+ FILE *stream ATTRIBUTE_UNUSED;
ggc_statistics *stats;
{
- int code;
-
/* Set the pointer so that during collection we will actually gather
the statistics. */
ggc_stats = stats;
@@ -226,58 +212,415 @@ ggc_print_common_statistics (stream, stats)
/* Then do one collection to fill in the statistics. */
ggc_collect ();
- /* Total the statistics. */
- for (code = 0; code < MAX_TREE_CODES; ++code)
+ /* At present, we don't really gather any interesting statistics. */
+
+ /* Don't gather statistics any more. */
+ ggc_stats = NULL;
+}
+
+/* Functions for saving and restoring GCable memory to disk. */
+
+static htab_t saving_htab;
+
+struct ptr_data
+{
+ void *obj;
+ void *note_ptr_cookie;
+ gt_note_pointers note_ptr_fn;
+ gt_handle_reorder reorder_fn;
+ size_t size;
+ void *new_addr;
+};
+
+#define POINTER_HASH(x) (hashval_t)((long)x >> 3)
+
+/* Register an object in the hash table. */
+
+int
+gt_pch_note_object (obj, note_ptr_cookie, note_ptr_fn)
+ void *obj;
+ void *note_ptr_cookie;
+ gt_note_pointers note_ptr_fn;
+{
+ struct ptr_data **slot;
+
+ if (obj == NULL || obj == (void *) 1)
+ return 0;
+
+ slot = (struct ptr_data **)
+ htab_find_slot_with_hash (saving_htab, obj, POINTER_HASH (obj),
+ INSERT);
+ if (*slot != NULL)
+ {
+ if ((*slot)->note_ptr_fn != note_ptr_fn
+ || (*slot)->note_ptr_cookie != note_ptr_cookie)
+ abort ();
+ return 0;
+ }
+
+ *slot = xcalloc (sizeof (struct ptr_data), 1);
+ (*slot)->obj = obj;
+ (*slot)->note_ptr_fn = note_ptr_fn;
+ (*slot)->note_ptr_cookie = note_ptr_cookie;
+ if (note_ptr_fn == gt_pch_p_S)
+ (*slot)->size = strlen (obj) + 1;
+ else
+ (*slot)->size = ggc_get_size (obj);
+ return 1;
+}
+
+/* Register an object in the hash table. */
+
+void
+gt_pch_note_reorder (obj, note_ptr_cookie, reorder_fn)
+ void *obj;
+ void *note_ptr_cookie;
+ gt_handle_reorder reorder_fn;
+{
+ struct ptr_data *data;
+
+ if (obj == NULL || obj == (void *) 1)
+ return;
+
+ data = htab_find_with_hash (saving_htab, obj, POINTER_HASH (obj));
+ if (data == NULL
+ || data->note_ptr_cookie != note_ptr_cookie)
+ abort ();
+
+ data->reorder_fn = reorder_fn;
+}
+
+/* Hash and equality functions for saving_htab, callbacks for htab_create. */
+
+static hashval_t
+saving_htab_hash (p)
+ const PTR p;
+{
+ return POINTER_HASH (((struct ptr_data *)p)->obj);
+}
+
+static int
+saving_htab_eq (p1, p2)
+ const PTR p1;
+ const PTR p2;
+{
+ return ((struct ptr_data *)p1)->obj == p2;
+}
+
+/* Handy state for the traversal functions. */
+
+struct traversal_state
+{
+ FILE *f;
+ struct ggc_pch_data *d;
+ size_t count;
+ struct ptr_data **ptrs;
+ size_t ptrs_i;
+};
+
+/* Callbacks for htab_traverse. */
+
+static int
+call_count (slot, state_p)
+ void **slot;
+ void *state_p;
+{
+ struct ptr_data *d = (struct ptr_data *)*slot;
+ struct traversal_state *state = (struct traversal_state *)state_p;
+
+ ggc_pch_count_object (state->d, d->obj, d->size);
+ state->count++;
+ return 1;
+}
+
+static int
+call_alloc (slot, state_p)
+ void **slot;
+ void *state_p;
+{
+ struct ptr_data *d = (struct ptr_data *)*slot;
+ struct traversal_state *state = (struct traversal_state *)state_p;
+
+ d->new_addr = ggc_pch_alloc_object (state->d, d->obj, d->size);
+ state->ptrs[state->ptrs_i++] = d;
+ return 1;
+}
+
+/* Callback for qsort. */
+
+static int
+compare_ptr_data (p1_p, p2_p)
+ const void *p1_p;
+ const void *p2_p;
+{
+ struct ptr_data *p1 = *(struct ptr_data *const *)p1_p;
+ struct ptr_data *p2 = *(struct ptr_data *const *)p2_p;
+ return (((size_t)p1->new_addr > (size_t)p2->new_addr)
+ - ((size_t)p1->new_addr < (size_t)p2->new_addr));
+}
+
+/* Callbacks for note_ptr_fn. */
+
+static void
+relocate_ptrs (ptr_p, state_p)
+ void *ptr_p;
+ void *state_p;
+{
+ void **ptr = (void **)ptr_p;
+ struct traversal_state *state ATTRIBUTE_UNUSED
+ = (struct traversal_state *)state_p;
+ struct ptr_data *result;
+
+ if (*ptr == NULL || *ptr == (void *)1)
+ return;
+
+ result = htab_find_with_hash (saving_htab, *ptr, POINTER_HASH (*ptr));
+ if (result == NULL)
+ abort ();
+ *ptr = result->new_addr;
+}
+
+/* Write out, after relocation, the pointers in TAB. */
+static void
+write_pch_globals (tab, state)
+ const struct ggc_root_tab * const *tab;
+ struct traversal_state *state;
+{
+ const struct ggc_root_tab *const *rt;
+ const struct ggc_root_tab *rti;
+ size_t i;
+
+ for (rt = tab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ for (i = 0; i < rti->nelt; i++)
+ {
+ void *ptr = *(void **)((char *)rti->base + rti->stride * i);
+ struct ptr_data *new_ptr;
+ if (ptr == NULL || ptr == (void *)1)
+ {
+ if (fwrite (&ptr, sizeof (void *), 1, state->f)
+ != 1)
+ fatal_io_error ("can't write PCH file");
+ }
+ else
+ {
+ new_ptr = htab_find_with_hash (saving_htab, ptr,
+ POINTER_HASH (ptr));
+ if (fwrite (&new_ptr->new_addr, sizeof (void *), 1, state->f)
+ != 1)
+ fatal_io_error ("can't write PCH file");
+ }
+ }
+}
+
+/* Hold the information we need to mmap the file back in. */
+
+struct mmap_info
+{
+ size_t offset;
+ size_t size;
+ void *preferred_base;
+};
+
+/* Write out the state of the compiler to F. */
+
+void
+gt_pch_save (f)
+ FILE *f;
+{
+ const struct ggc_root_tab *const *rt;
+ const struct ggc_root_tab *rti;
+ size_t i;
+ struct traversal_state state;
+ char *this_object = NULL;
+ size_t this_object_size = 0;
+ struct mmap_info mmi;
+ size_t page_size = getpagesize();
+
+ gt_pch_save_stringpool ();
+
+ saving_htab = htab_create (50000, saving_htab_hash, saving_htab_eq, free);
+
+ for (rt = gt_ggc_rtab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ for (i = 0; i < rti->nelt; i++)
+ (*rti->pchw)(*(void **)((char *)rti->base + rti->stride * i));
+
+ for (rt = gt_pch_cache_rtab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ for (i = 0; i < rti->nelt; i++)
+ (*rti->pchw)(*(void **)((char *)rti->base + rti->stride * i));
+
+ /* Prepare the objects for writing, determine addresses and such. */
+ state.f = f;
+ state.d = init_ggc_pch();
+ state.count = 0;
+ htab_traverse (saving_htab, call_count, &state);
+
+ mmi.size = ggc_pch_total_size (state.d);
+
+ /* Try to arrange things so that no relocation is necessary,
+ but don't try very hard. On most platforms, this will always work,
+ and on the rest it's a lot of work to do better. */
+#if HAVE_MMAP_FILE
+ mmi.preferred_base = mmap (NULL, mmi.size,
+ PROT_READ | PROT_WRITE, MAP_PRIVATE,
+ fileno (state.f), 0);
+ if (mmi.preferred_base == (void *)-1)
+ mmi.preferred_base = NULL;
+ else
+ munmap (mmi.preferred_base, mmi.size);
+#else /* HAVE_MMAP_FILE */
+ mmi.preferred_base = NULL;
+#endif /* HAVE_MMAP_FILE */
+
+ ggc_pch_this_base (state.d, mmi.preferred_base);
+
+ state.ptrs = xmalloc (state.count * sizeof (*state.ptrs));
+ state.ptrs_i = 0;
+ htab_traverse (saving_htab, call_alloc, &state);
+ qsort (state.ptrs, state.count, sizeof (*state.ptrs), compare_ptr_data);
+
+ /* Write out all the scalar variables. */
+ for (rt = gt_pch_scalar_rtab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ if (fwrite (rti->base, rti->stride, 1, f) != 1)
+ fatal_io_error ("can't write PCH file");
+
+ /* Write out all the global pointers, after translation. */
+ write_pch_globals (gt_ggc_rtab, &state);
+ write_pch_globals (gt_pch_cache_rtab, &state);
+
+ ggc_pch_prepare_write (state.d, state.f);
+
+ /* Pad the PCH file so that the mmaped area starts on a page boundary. */
+ {
+ off_t o;
+ o = ftello (state.f) + sizeof (mmi);
+ if (o == (off_t) -1)
+ fatal_io_error ("can't get position in PCH file");
+ mmi.offset = page_size - o % page_size;
+ if (mmi.offset == page_size)
+ mmi.offset = 0;
+ mmi.offset += o;
+ }
+ if (fwrite (&mmi, sizeof (mmi), 1, state.f) != 1)
+ fatal_io_error ("can't write PCH file");
+ if (mmi.offset != 0
+ && fseek (state.f, mmi.offset, SEEK_SET) != 0)
+ fatal_io_error ("can't write padding to PCH file");
+
+ /* Actually write out the objects. */
+ for (i = 0; i < state.count; i++)
{
- stats->total_num_trees += stats->num_trees[code];
- stats->total_size_trees += stats->size_trees[code];
+ if (this_object_size < state.ptrs[i]->size)
+ {
+ this_object_size = state.ptrs[i]->size;
+ this_object = xrealloc (this_object, this_object_size);
+ }
+ memcpy (this_object, state.ptrs[i]->obj, state.ptrs[i]->size);
+ if (state.ptrs[i]->reorder_fn != NULL)
+ state.ptrs[i]->reorder_fn (state.ptrs[i]->obj,
+ state.ptrs[i]->note_ptr_cookie,
+ relocate_ptrs, &state);
+ state.ptrs[i]->note_ptr_fn (state.ptrs[i]->obj,
+ state.ptrs[i]->note_ptr_cookie,
+ relocate_ptrs, &state);
+ ggc_pch_write_object (state.d, state.f, state.ptrs[i]->obj,
+ state.ptrs[i]->new_addr, state.ptrs[i]->size);
+ if (state.ptrs[i]->note_ptr_fn != gt_pch_p_S)
+ memcpy (state.ptrs[i]->obj, this_object, state.ptrs[i]->size);
}
- for (code = 0; code < NUM_RTX_CODE; ++code)
+ ggc_pch_finish (state.d, state.f);
+
+ free (state.ptrs);
+ htab_delete (saving_htab);
+}
+
+/* Read the state of the compiler back in from F. */
+
+void
+gt_pch_restore (f)
+ FILE *f;
+{
+ const struct ggc_root_tab *const *rt;
+ const struct ggc_root_tab *rti;
+ size_t i;
+ struct mmap_info mmi;
+ void *addr;
+
+ /* Delete any deletable objects. This makes ggc_pch_read much
+ faster, as it can be sure that no GCable objects remain other
+ than the ones just read in. */
+ for (rt = gt_ggc_deletable_rtab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ memset (rti->base, 0, rti->stride);
+
+ /* Read in all the scalar variables. */
+ for (rt = gt_pch_scalar_rtab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ if (fread (rti->base, rti->stride, 1, f) != 1)
+ fatal_io_error ("can't read PCH file");
+
+ /* Read in all the global pointers, in 6 easy loops. */
+ for (rt = gt_ggc_rtab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ for (i = 0; i < rti->nelt; i++)
+ if (fread ((char *)rti->base + rti->stride * i,
+ sizeof (void *), 1, f) != 1)
+ fatal_io_error ("can't read PCH file");
+
+ for (rt = gt_pch_cache_rtab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ for (i = 0; i < rti->nelt; i++)
+ if (fread ((char *)rti->base + rti->stride * i,
+ sizeof (void *), 1, f) != 1)
+ fatal_io_error ("can't read PCH file");
+
+ if (fread (&mmi, sizeof (mmi), 1, f) != 1)
+ fatal_io_error ("can't read PCH file");
+
+#if HAVE_MMAP_FILE
+ addr = mmap (mmi.preferred_base, mmi.size,
+ PROT_READ | PROT_WRITE, MAP_PRIVATE,
+ fileno (f), mmi.offset);
+#else
+ addr = (void *)-1;
+#endif
+ if (addr == (void *)-1)
{
- stats->total_num_rtxs += stats->num_rtxs[code];
- stats->total_size_rtxs += stats->size_rtxs[code];
+ addr = xmalloc (mmi.size);
+ if (fseek (f, mmi.offset, SEEK_SET) != 0
+ || fread (&mmi, mmi.size, 1, f) != 1)
+ fatal_io_error ("can't read PCH file");
}
+ else if (fseek (f, mmi.offset + mmi.size, SEEK_SET) != 0)
+ fatal_io_error ("can't read PCH file");
- /* Print the statistics for trees. */
- fprintf (stream, "\n%-17s%10s %16s %10s\n", "Tree",
- "Number", "Bytes", "% Total");
- for (code = 0; code < MAX_TREE_CODES; ++code)
- if (ggc_stats->num_trees[code])
- {
- fprintf (stream, "%-17s%10u%16ld%c %10.3f\n",
- tree_code_name[code],
- ggc_stats->num_trees[code],
- SCALE (ggc_stats->size_trees[code]),
- LABEL (ggc_stats->size_trees[code]),
- (100 * ((double) ggc_stats->size_trees[code])
- / ggc_stats->total_size_trees));
- }
- fprintf (stream,
- "%-17s%10u%16ld%c\n", "Total",
- ggc_stats->total_num_trees,
- SCALE (ggc_stats->total_size_trees),
- LABEL (ggc_stats->total_size_trees));
-
- /* Print the statistics for RTL. */
- fprintf (stream, "\n%-17s%10s %16s %10s\n", "RTX",
- "Number", "Bytes", "% Total");
- for (code = 0; code < NUM_RTX_CODE; ++code)
- if (ggc_stats->num_rtxs[code])
- {
- fprintf (stream, "%-17s%10u%16ld%c %10.3f\n",
- rtx_name[code],
- ggc_stats->num_rtxs[code],
- SCALE (ggc_stats->size_rtxs[code]),
- LABEL (ggc_stats->size_rtxs[code]),
- (100 * ((double) ggc_stats->size_rtxs[code])
- / ggc_stats->total_size_rtxs));
- }
- fprintf (stream,
- "%-17s%10u%16ld%c\n", "Total",
- ggc_stats->total_num_rtxs,
- SCALE (ggc_stats->total_size_rtxs),
- LABEL (ggc_stats->total_size_rtxs));
+ ggc_pch_read (f, addr);
- /* Don't gather statistics any more. */
- ggc_stats = NULL;
+ if (addr != mmi.preferred_base)
+ {
+ for (rt = gt_ggc_rtab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ for (i = 0; i < rti->nelt; i++)
+ {
+ char **ptr = (char **)((char *)rti->base + rti->stride * i);
+ if (*ptr != NULL)
+ *ptr += (size_t)addr - (size_t)mmi.preferred_base;
+ }
+
+ for (rt = gt_pch_cache_rtab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ for (i = 0; i < rti->nelt; i++)
+ {
+ char **ptr = (char **)((char *)rti->base + rti->stride * i);
+ if (*ptr != NULL)
+ *ptr += (size_t)addr - (size_t)mmi.preferred_base;
+ }
+
+ sorry ("had to relocate PCH");
+ }
+
+ gt_pch_restore_stringpool ();
}
diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
index 537f302578a..a150c5a88e6 100644
--- a/gcc/ggc-page.c
+++ b/gcc/ggc-page.c
@@ -1,5 +1,5 @@
/* "Bag-of-pages" garbage collector for the GNU compiler.
- Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
@@ -147,6 +147,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
the indicated ORDER. */
#define OBJECTS_PER_PAGE(ORDER) objects_per_page_table[ORDER]
+/* The number of objects in P. */
+#define OBJECTS_IN_PAGE(P) ((P)->bytes / OBJECT_SIZE ((P)->order))
+
/* The size of an object on a page of the indicated ORDER. */
#define OBJECT_SIZE(ORDER) object_size_table[ORDER]
@@ -202,6 +205,15 @@ struct max_alignment {
#define MAX_ALIGNMENT (offsetof (struct max_alignment, u))
+/* Compute the smallest nonnegative number which when added to X gives
+ a multiple of F. */
+
+#define ROUND_UP_VALUE(x, f) ((f) - 1 - ((f) - 1 + (x)) % (f))
+
+/* Compute the smallest multiple of F that is >= X. */
+
+#define ROUND_UP(x, f) (CEIL (x, f) * (f))
+
/* The Ith entry is the number of objects on a page or order I. */
static unsigned objects_per_page_table[NUM_ORDERS];
@@ -1172,7 +1184,7 @@ init_ggc ()
/* If S is not a multiple of the MAX_ALIGNMENT, then round it up
so that we're sure of getting aligned memory. */
- s = CEIL (s, MAX_ALIGNMENT) * MAX_ALIGNMENT;
+ s = ROUND_UP (s, MAX_ALIGNMENT);
object_size_table[order] = s;
}
@@ -1225,7 +1237,7 @@ ggc_recalculate_in_use_p (p)
/* Because the past-the-end bit in in_use_p is always set, we
pretend there is one additional object. */
- num_objects = OBJECTS_PER_PAGE (p->order) + 1;
+ num_objects = OBJECTS_IN_PAGE (p) + 1;
/* Reset the free object count. */
p->num_free_objects = num_objects;
@@ -1294,12 +1306,13 @@ clear_marks ()
for (order = 2; order < NUM_ORDERS; order++)
{
- size_t num_objects = OBJECTS_PER_PAGE (order);
- size_t bitmap_size = BITMAP_SIZE (num_objects + 1);
page_entry *p;
for (p = G.pages[order]; p != NULL; p = p->next)
{
+ size_t num_objects = OBJECTS_IN_PAGE (p);
+ size_t bitmap_size = BITMAP_SIZE (num_objects + 1);
+
#ifdef ENABLE_CHECKING
/* The data should be page-aligned. */
if ((size_t) p->page & (G.pagesize - 1))
@@ -1342,7 +1355,7 @@ sweep_pages ()
placed at the end of the list. */
page_entry * const last = G.page_tails[order];
- size_t num_objects = OBJECTS_PER_PAGE (order);
+ size_t num_objects;
size_t live_objects;
page_entry *p, *previous;
int done;
@@ -1358,6 +1371,8 @@ sweep_pages ()
/* Loop until all entries have been examined. */
done = (p == last);
+
+ num_objects = OBJECTS_IN_PAGE (p);
/* Add all live objects on this page to the count of
allocated memory. */
@@ -1445,12 +1460,12 @@ poison_pages ()
for (order = 2; order < NUM_ORDERS; order++)
{
- size_t num_objects = OBJECTS_PER_PAGE (order);
size_t size = OBJECT_SIZE (order);
page_entry *p;
for (p = G.pages[order]; p != NULL; p = p->next)
{
+ size_t num_objects;
size_t i;
if (p->context_depth != G.context_depth)
@@ -1460,6 +1475,7 @@ poison_pages ()
contexts. */
continue;
+ num_objects = OBJECTS_IN_PAGE (p);
for (i = 0; i < num_objects; i++)
{
size_t word, bit;
@@ -1581,11 +1597,11 @@ ggc_print_statistics ()
for (p = G.pages[i]; p; p = p->next)
{
allocated += p->bytes;
- in_use +=
- (OBJECTS_PER_PAGE (i) - p->num_free_objects) * OBJECT_SIZE (i);
+ in_use +=
+ (OBJECTS_IN_PAGE (p) - p->num_free_objects) * OBJECT_SIZE (i);
overhead += (sizeof (page_entry) - sizeof (long)
- + BITMAP_SIZE (OBJECTS_PER_PAGE (i) + 1));
+ + BITMAP_SIZE (OBJECTS_IN_PAGE (p) + 1));
}
fprintf (stderr, "%-5lu %10lu%c %10lu%c %10lu%c\n",
(unsigned long) OBJECT_SIZE (i),
@@ -1599,3 +1615,225 @@ ggc_print_statistics ()
SCALE (G.allocated), LABEL(G.allocated),
SCALE (total_overhead), LABEL (total_overhead));
}
+
+struct ggc_pch_data
+{
+ struct ggc_pch_ondisk
+ {
+ unsigned totals[NUM_ORDERS];
+ } d;
+ size_t base[NUM_ORDERS];
+ size_t written[NUM_ORDERS];
+};
+
+struct ggc_pch_data *
+init_ggc_pch ()
+{
+ return xcalloc (sizeof (struct ggc_pch_data), 1);
+}
+
+void
+ggc_pch_count_object (d, x, size)
+ struct ggc_pch_data *d;
+ void *x ATTRIBUTE_UNUSED;
+ size_t size;
+{
+ unsigned order;
+
+ if (size <= 256)
+ order = size_lookup[size];
+ else
+ {
+ order = 9;
+ while (size > OBJECT_SIZE (order))
+ order++;
+ }
+
+ d->d.totals[order]++;
+}
+
+size_t
+ggc_pch_total_size (d)
+ struct ggc_pch_data *d;
+{
+ size_t a = 0;
+ unsigned i;
+
+ for (i = 0; i < NUM_ORDERS; i++)
+ a += ROUND_UP (d->d.totals[i] * OBJECT_SIZE (i), G.pagesize);
+ return a;
+}
+
+void
+ggc_pch_this_base (d, base)
+ struct ggc_pch_data *d;
+ void *base;
+{
+ size_t a = (size_t) base;
+ unsigned i;
+
+ for (i = 0; i < NUM_ORDERS; i++)
+ {
+ d->base[i] = a;
+ a += ROUND_UP (d->d.totals[i] * OBJECT_SIZE (i), G.pagesize);
+ }
+}
+
+
+char *
+ggc_pch_alloc_object (d, x, size)
+ struct ggc_pch_data *d;
+ void *x ATTRIBUTE_UNUSED;
+ size_t size;
+{
+ unsigned order;
+ char *result;
+
+ if (size <= 256)
+ order = size_lookup[size];
+ else
+ {
+ order = 9;
+ while (size > OBJECT_SIZE (order))
+ order++;
+ }
+
+ result = (char *) d->base[order];
+ d->base[order] += OBJECT_SIZE (order);
+ return result;
+}
+
+void
+ggc_pch_prepare_write (d, f)
+ struct ggc_pch_data * d ATTRIBUTE_UNUSED;
+ FILE * f ATTRIBUTE_UNUSED;
+{
+ /* Nothing to do. */
+}
+
+void
+ggc_pch_write_object (d, f, x, newx, size)
+ struct ggc_pch_data * d ATTRIBUTE_UNUSED;
+ FILE *f;
+ void *x;
+ void *newx ATTRIBUTE_UNUSED;
+ size_t size;
+{
+ unsigned order;
+
+ if (size <= 256)
+ order = size_lookup[size];
+ else
+ {
+ order = 9;
+ while (size > OBJECT_SIZE (order))
+ order++;
+ }
+
+ if (fwrite (x, size, 1, f) != 1)
+ fatal_io_error ("can't write PCH file");
+
+ /* In the current implementation, SIZE is always equal to
+ OBJECT_SIZE (order) and so the fseek is never executed. */
+ if (size != OBJECT_SIZE (order)
+ && fseek (f, OBJECT_SIZE (order) - size, SEEK_CUR) != 0)
+ fatal_io_error ("can't write PCH file");
+
+ d->written[order]++;
+ if (d->written[order] == d->d.totals[order]
+ && fseek (f, ROUND_UP_VALUE (d->d.totals[order] * OBJECT_SIZE (order),
+ G.pagesize),
+ SEEK_CUR) != 0)
+ fatal_io_error ("can't write PCH file");
+}
+
+void
+ggc_pch_finish (d, f)
+ struct ggc_pch_data * d;
+ FILE *f;
+{
+ if (fwrite (&d->d, sizeof (d->d), 1, f) != 1)
+ fatal_io_error ("can't write PCH file");
+ free (d);
+}
+
+void
+ggc_pch_read (f, addr)
+ FILE *f;
+ void *addr;
+{
+ struct ggc_pch_ondisk d;
+ unsigned i;
+ char *offs = addr;
+
+ /* We've just read in a PCH file. So, every object that used to be allocated
+ is now free. */
+ clear_marks ();
+#ifdef GGC_POISON
+ poison_pages ();
+#endif
+
+ /* No object read from a PCH file should ever be freed. So, set the
+ context depth to 1, and set the depth of all the currently-allocated
+ pages to be 1 too. PCH pages will have depth 0. */
+ if (G.context_depth != 0)
+ abort ();
+ G.context_depth = 1;
+ for (i = 0; i < NUM_ORDERS; i++)
+ {
+ page_entry *p;
+ for (p = G.pages[i]; p != NULL; p = p->next)
+ p->context_depth = G.context_depth;
+ }
+
+ /* Allocate the appropriate page-table entries for the pages read from
+ the PCH file. */
+ if (fread (&d, sizeof (d), 1, f) != 1)
+ fatal_io_error ("can't read PCH file");
+
+ for (i = 0; i < NUM_ORDERS; i++)
+ {
+ struct page_entry *entry;
+ char *pte;
+ size_t bytes;
+ size_t num_objs;
+ size_t j;
+
+ if (d.totals[i] == 0)
+ continue;
+
+ bytes = ROUND_UP (d.totals[i] * OBJECT_SIZE (i), G.pagesize);
+ num_objs = bytes / OBJECT_SIZE (i);
+ entry = xcalloc (1, (sizeof (struct page_entry)
+ - sizeof (long)
+ + BITMAP_SIZE (num_objs + 1)));
+ entry->bytes = bytes;
+ entry->page = offs;
+ entry->context_depth = 0;
+ offs += bytes;
+ entry->num_free_objects = 0;
+ entry->order = i;
+
+ for (j = 0;
+ j + HOST_BITS_PER_LONG <= num_objs + 1;
+ j += HOST_BITS_PER_LONG)
+ entry->in_use_p[j / HOST_BITS_PER_LONG] = -1;
+ for (; j < num_objs + 1; j++)
+ entry->in_use_p[j / HOST_BITS_PER_LONG]
+ |= 1L << (j % HOST_BITS_PER_LONG);
+
+ for (pte = entry->page;
+ pte < entry->page + entry->bytes;
+ pte += G.pagesize)
+ set_page_table_entry (pte, entry);
+
+ if (G.page_tails[i] != NULL)
+ G.page_tails[i]->next = entry;
+ else
+ G.pages[i] = entry;
+ G.page_tails[i] = entry;
+ }
+
+ /* Update the statistics. */
+ G.allocated = G.allocated_last_gc = offs - (char *)addr;
+}
diff --git a/gcc/ggc-simple.c b/gcc/ggc-simple.c
index 554ef722669..65bc1b64839 100644
--- a/gcc/ggc-simple.c
+++ b/gcc/ggc-simple.c
@@ -1,5 +1,5 @@
/* Simple garbage collection for the GNU compiler.
- Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
@@ -28,6 +28,7 @@
#include "flags.h"
#include "varray.h"
#include "ggc.h"
+#include "toplev.h"
#include "timevar.h"
#include "params.h"
@@ -490,16 +491,90 @@ ggc_print_statistics ()
fprintf (stderr, "\n\
Total internal data (bytes)\t%ld%c\n\
-Number of leaves in tree\t%d\n\
+Number of leaves in tree\t%lu\n\
Average leaf depth\t\t%.1f\n",
SCALE(G.objects * offsetof (struct ggc_mem, u)),
LABEL(G.objects * offsetof (struct ggc_mem, u)),
- nleaf, (double)sumdepth / (double)nleaf);
+ (unsigned long)nleaf, (double)sumdepth / (double)nleaf);
/* Report overall memory usage. */
fprintf (stderr, "\n\
-Total objects allocated\t\t%d\n\
+Total objects allocated\t\t%ld\n\
Total memory in GC arena\t%ld%c\n",
- G.objects,
+ (unsigned long)G.objects,
SCALE(G.allocated), LABEL(G.allocated));
}
+
+struct ggc_pch_data *
+init_ggc_pch ()
+{
+ sorry ("Generating PCH files is not supported when using ggc-simple.c");
+ /* It could be supported, but the code is not yet written. */
+ return NULL;
+}
+
+void
+ggc_pch_count_object (d, x, size)
+ struct ggc_pch_data *d ATTRIBUTE_UNUSED;
+ void *x ATTRIBUTE_UNUSED;
+ size_t size ATTRIBUTE_UNUSED;
+{
+}
+
+size_t
+ggc_pch_total_size (d)
+ struct ggc_pch_data *d ATTRIBUTE_UNUSED;
+{
+ return 0;
+}
+
+void
+ggc_pch_this_base (d, base)
+ struct ggc_pch_data *d ATTRIBUTE_UNUSED;
+ void *base ATTRIBUTE_UNUSED;
+{
+}
+
+
+char *
+ggc_pch_alloc_object (d, x, size)
+ struct ggc_pch_data *d ATTRIBUTE_UNUSED;
+ void *x ATTRIBUTE_UNUSED;
+ size_t size ATTRIBUTE_UNUSED;
+{
+ return NULL;
+}
+
+void
+ggc_pch_prepare_write (d, f)
+ struct ggc_pch_data * d ATTRIBUTE_UNUSED;
+ FILE * f ATTRIBUTE_UNUSED;
+{
+}
+
+void
+ggc_pch_write_object (d, f, x, newx, size)
+ struct ggc_pch_data * d ATTRIBUTE_UNUSED;
+ FILE *f ATTRIBUTE_UNUSED;
+ void *x ATTRIBUTE_UNUSED;
+ void *newx ATTRIBUTE_UNUSED;
+ size_t size ATTRIBUTE_UNUSED;
+{
+}
+
+void
+ggc_pch_finish (d, f)
+ struct ggc_pch_data * d ATTRIBUTE_UNUSED;
+ FILE *f ATTRIBUTE_UNUSED;
+{
+}
+
+void
+ggc_pch_read (f, addr)
+ FILE *f ATTRIBUTE_UNUSED;
+ void *addr ATTRIBUTE_UNUSED;
+{
+ /* This should be impossible, since we won't generate any valid PCH
+ files for this configuration. */
+ abort ();
+}
diff --git a/gcc/ggc.h b/gcc/ggc.h
index 4cd6242ee92..86ae60a7d99 100644
--- a/gcc/ggc.h
+++ b/gcc/ggc.h
@@ -18,9 +18,6 @@ along with GCC; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
-#include "varray.h"
-#include "gtype-desc.h"
-
/* Symbols are marked with `ggc' for `gcc gc' so as not to interfere with
an external gc library that might be linked in. */
@@ -29,10 +26,39 @@ extern const char empty_string[]; /* empty string */
extern const char digit_vector[]; /* "0" .. "9" */
#define digit_string(d) (digit_vector + ((d) * 2))
-/* Manipulate global roots that are needed between calls to gc.
- THIS ROUTINE IS OBSOLETE, do not use it for new code. */
-extern void ggc_add_root PARAMS ((void *base, int nelt,
- int size, void (*)(void *)));
+/* Internal functions and data structures used by the GTY
+ machinery. */
+
+/* The first parameter is a pointer to a pointer, the second a cookie. */
+typedef void (*gt_pointer_operator) PARAMS ((void *, void *));
+
+#include "gtype-desc.h"
+
+/* One of these applies its third parameter (with cookie in the fourth
+ parameter) to each pointer in the object pointed to by the first
+ parameter, using the second parameter. */
+typedef void (*gt_note_pointers)
+ PARAMS ((void *, void *, gt_pointer_operator, void *));
+
+/* One of these is called before objects are re-ordered in memory.
+ The first parameter is the original object, the second is the
+ subobject that has had its pointers reordered, the third parameter
+ can compute the new values of a pointer when given the cookie in
+ the fourth parameter. */
+typedef void (*gt_handle_reorder)
+ PARAMS ((void *, void *, gt_pointer_operator, void *));
+
+/* Used by the gt_pch_n_* routines. Register an object in the hash table. */
+extern int gt_pch_note_object
+ PARAMS ((void *, void *, gt_note_pointers));
+
+/* Used by the gt_pch_n_* routines. Register that an object has a reorder
+ function. */
+extern void gt_pch_note_reorder
+ PARAMS ((void *, void *, gt_handle_reorder));
+
+/* Mark the object in the first parameter and anything it points to. */
+typedef void (*gt_pointer_walker) PARAMS ((void *));
/* Structures for the easy way to mark roots.
In an array, terminated by having base == NULL.*/
@@ -40,12 +66,15 @@ struct ggc_root_tab {
void *base;
size_t nelt;
size_t stride;
- void (*cb) PARAMS ((void *));
+ gt_pointer_walker cb;
+ gt_pointer_walker pchw;
};
-#define LAST_GGC_ROOT_TAB { NULL, 0, 0, NULL }
+#define LAST_GGC_ROOT_TAB { NULL, 0, 0, NULL, NULL }
/* Pointers to arrays of ggc_root_tab, terminated by NULL. */
extern const struct ggc_root_tab * const gt_ggc_rtab[];
extern const struct ggc_root_tab * const gt_ggc_deletable_rtab[];
+extern const struct ggc_root_tab * const gt_pch_cache_rtab[];
+extern const struct ggc_root_tab * const gt_pch_scalar_rtab[];
/* Structure for hash table cache marking. */
struct htab;
@@ -53,23 +82,19 @@ struct ggc_cache_tab {
struct htab * *base;
size_t nelt;
size_t stride;
- void (*cb) PARAMS ((void *));
+ gt_pointer_walker cb;
+ gt_pointer_walker pchw;
int (*marked_p) PARAMS ((const void *));
};
-#define LAST_GGC_CACHE_TAB { NULL, 0, 0, NULL, NULL }
+#define LAST_GGC_CACHE_TAB { NULL, 0, 0, NULL, NULL, NULL }
/* Pointers to arrays of ggc_cache_tab, terminated by NULL. */
extern const struct ggc_cache_tab * const gt_ggc_cache_rtab[];
-extern void ggc_mark_roots PARAMS ((void));
-
/* If EXPR is not NULL and previously unmarked, mark it and evaluate
to true. Otherwise evaluate to false. */
#define ggc_test_and_set_mark(EXPR) \
((EXPR) != NULL && ((void *) (EXPR)) != (void *) 1 && ! ggc_set_mark (EXPR))
-#define ggc_mark_rtx gt_ggc_m_7rtx_def
-#define ggc_mark_tree gt_ggc_m_9tree_node
-
#define ggc_mark(EXPR) \
do { \
const void *const a__ = (EXPR); \
@@ -77,11 +102,45 @@ extern void ggc_mark_roots PARAMS ((void));
ggc_set_mark (a__); \
} while (0)
-/* A GC implementation must provide these functions. */
+/* Actually set the mark on a particular region of memory, but don't
+ follow pointers. This function is called by ggc_mark_*. It
+ returns zero if the object was not previously marked; non-zero if
+ the object was already marked, or if, for any other reason,
+ pointers in this data structure should not be traversed. */
+extern int ggc_set_mark PARAMS ((const void *));
+
+/* Return 1 if P has been marked, zero otherwise.
+ P must have been allocated by the GC allocator; it mustn't point to
+ static objects, stack variables, or memory allocated with malloc. */
+extern int ggc_marked_p PARAMS ((const void *));
+
+/* Mark the entries in the string pool. */
+extern void ggc_mark_stringpool PARAMS ((void));
+
+/* Call ggc_set_mark on all the roots. */
+
+extern void ggc_mark_roots PARAMS ((void));
+
+/* Save and restore the string pool entries for PCH. */
+
+extern void gt_pch_save_stringpool PARAMS ((void));
+extern void gt_pch_restore_stringpool PARAMS ((void));
+
+/* PCH and GGC handling for strings, mostly trivial. */
+
+extern void gt_pch_p_S PARAMS ((void *, void *,
+ gt_pointer_operator, void *));
+extern void gt_pch_n_S PARAMS ((const void *));
+extern void gt_ggc_m_S PARAMS ((void *));
+
+/* Initialise the string pool. */
+extern void init_stringpool PARAMS ((void));
+
+/* A GC implementation must provide these functions. They are internal
+ to the GC system. */
/* Initialize the garbage collector. */
extern void init_ggc PARAMS ((void));
-extern void init_stringpool PARAMS ((void));
/* Start a new GGC context. Memory allocated in previous contexts
will not be collected while the new context is active. */
@@ -91,6 +150,48 @@ extern void ggc_push_context PARAMS ((void));
will be merged with the old context. */
extern void ggc_pop_context PARAMS ((void));
+struct ggc_pch_data;
+
+/* Return a new ggc_pch_data structure. */
+extern struct ggc_pch_data *init_ggc_pch PARAMS ((void));
+
+/* The second parameter and third parameters give the address and size
+ of an object. Update the ggc_pch_data structure with as much of
+ that information as is necessary. */
+extern void ggc_pch_count_object PARAMS ((struct ggc_pch_data *,
+ void *, size_t));
+
+/* Return the total size of the data to be written to hold all
+ the objects previously passed to ggc_pch_count_object. */
+extern size_t ggc_pch_total_size PARAMS ((struct ggc_pch_data *));
+
+/* The objects, when read, will most likely be at the address
+ in the second parameter. */
+extern void ggc_pch_this_base PARAMS ((struct ggc_pch_data *,
+ void *));
+
+/* Assuming that the objects really do end up at the address
+ passed to ggc_pch_this_base, return the address of this object. */
+extern char *ggc_pch_alloc_object PARAMS ((struct ggc_pch_data *,
+ void *, size_t));
+
+/* Write out any initial information required. */
+extern void ggc_pch_prepare_write PARAMS ((struct ggc_pch_data *,
+ FILE *));
+/* Write out this object, including any padding. */
+extern void ggc_pch_write_object PARAMS ((struct ggc_pch_data *,
+ FILE *, void *, void *,
+ size_t));
+/* All objects have been written, write out any final information
+ required. */
+extern void ggc_pch_finish PARAMS ((struct ggc_pch_data *,
+ FILE *));
+
+/* A PCH file has just been read in at the address specified second
+ parameter. Set up the GC implementation for the new objects. */
+extern void ggc_pch_read PARAMS ((FILE *, void *));
+
+
/* Allocation. */
/* The internal primitive. */
@@ -115,6 +216,13 @@ extern void *ggc_calloc PARAMS ((size_t, size_t));
#define htab_create_ggc(SIZE, HASH, EQ, DEL) \
htab_create_alloc (SIZE, HASH, EQ, DEL, ggc_calloc, NULL)
+#define splay_tree_new_ggc(COMPARE) \
+ splay_tree_new_with_allocator (COMPARE, NULL, NULL, \
+ &ggc_splay_alloc, &ggc_splay_dont_free, \
+ NULL)
+extern PTR ggc_splay_alloc PARAMS ((int, void *));
+extern void ggc_splay_dont_free PARAMS ((void *, void *));
+
/* Allocate a gc-able string, and fill it with LENGTH bytes from CONTENTS.
If LENGTH is -1, then CONTENTS is assumed to be a
null-terminated string and the memory sized accordingly. */
@@ -128,47 +236,25 @@ extern const char *ggc_alloc_string PARAMS ((const char *contents,
function is called, not during allocations. */
extern void ggc_collect PARAMS ((void));
-/* Actually set the mark on a particular region of memory, but don't
- follow pointers. This function is called by ggc_mark_*. It
- returns zero if the object was not previously marked; nonzero if
- the object was already marked, or if, for any other reason,
- pointers in this data structure should not be traversed. */
-extern int ggc_set_mark PARAMS ((const void *));
+/* Return the number of bytes allocated at the indicated address. */
+extern size_t ggc_get_size PARAMS ((const void *));
-/* Return 1 if P has been marked, zero otherwise.
- P must have been allocated by the GC allocator; it mustn't point to
- static objects, stack variables, or memory allocated with malloc. */
-extern int ggc_marked_p PARAMS ((const void *));
+/* Write out all GCed objects to F. */
+extern void gt_pch_save PARAMS ((FILE *f));
+/* Read objects previously saved with gt_pch_save from F. */
+extern void gt_pch_restore PARAMS ((FILE *f));
+
/* Statistics. */
/* This structure contains the statistics common to all collectors.
Particular collectors can extend this structure. */
typedef struct ggc_statistics
{
- /* The Ith element is the number of nodes allocated with code I. */
- unsigned num_trees[256];
- /* The Ith element is the number of bytes allocated by nodes with
- code I. */
- size_t size_trees[256];
- /* The Ith element is the number of nodes allocated with code I. */
- unsigned num_rtxs[256];
- /* The Ith element is the number of bytes allocated by nodes with
- code I. */
- size_t size_rtxs[256];
- /* The total size of the tree nodes allocated. */
- size_t total_size_trees;
- /* The total size of the RTL nodes allocated. */
- size_t total_size_rtxs;
- /* The total number of tree nodes allocated. */
- unsigned total_num_trees;
- /* The total number of RTL nodes allocated. */
- unsigned total_num_rtxs;
+ /* At present, we don't really gather any interesting statistics. */
+ int unused;
} ggc_statistics;
-/* Return the number of bytes allocated at the indicated address. */
-extern size_t ggc_get_size PARAMS ((const void *));
-
/* Used by the various collectors to gather and print statistics that
do not depend on the collector in use. */
extern void ggc_print_common_statistics PARAMS ((FILE *, ggc_statistics *));
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index 34d39a45214..00b5e50a9fb 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -1,3 +1,77 @@
+2003-01-09 Geoffrey Keating <geoffk@apple.com>
+
+ Merge from pch-branch:
+
+ 2002-12-02 Geoffrey Keating <geoffk@apple.com>
+
+ * Make-lang.in (java/gjavah.o): Update dependencies.
+ * gjavah.c: Include ggc.h.
+
+ 2002-08-16 Geoffrey Keating <geoffk@redhat.com>
+
+ * Make-lang.in (GCJH_OBJS): Add ggc-none.o.
+ (JCFDUMP_OBJS): Add ggc-none.o.
+ (java/jcf-dump.o): Depend on GGC_H.
+ * jcf-reader.c (jcf_parse_constant_pool): Use ggc_alloc to allocate
+ CPool substructures.
+ * jcf-parse.c (process_zip_dir): Use ggc_alloc to allocate JCFs.
+ * jcf-dump.c: Include ggc.h.
+
+ 2002-08-08 Geoffrey Keating <geoffk@redhat.com>
+
+ * jcf.h (union cpool_entry): New.
+ (struct CPool): Use gengtype to mark. Change field 'data' to be
+ an array of unions.
+ (struct JCF): Use gengtype to mark.
+ (CPOOL_UINT): Update for new cpool_entry type.
+ (CPOOL_USHORT1): Likewise.
+ (CPOOL_USHORT2): Likewise.
+ (CPOOL_FINISH): Use GC to free cpool subfields.
+ * parse.h (struct parser_ctxt): Mark field current_jcf.
+ * lex.c (java_init_lex): Use GC to allocate struct JCF.
+ * jcf-parse.c (HANDLE_CONSTANT_Utf8): Update for new cpool_entry type.
+ (main_jcf): Use gengtype to mark.
+ (ggc_mark_jcf): Delete.
+ (get_constant): Update for new cpool_entry type.
+ (give_name_to_class): Likewise.
+ (get_class_constant): Likewise.
+ (init_outgoing_cpool): Use GGC to allocate struct CPool.
+ (java_parse_file): Use GGC to allocate struct JCF.
+ (init_jcf_parse): Don't call ggc_add_root.
+ * jcf-reader.c (jcf_parse_constant_pool): Update for new
+ cpool_entry type.
+ * java-tree.h (current_jcf): Use gengtype to mark.
+ (CPOOL_UTF): Update for new cpool_entry type.
+ (outgoing_cpool): Use gengtype to mark.
+ (struct lang_type): GC struct JCF and struct CPool.
+ * config-lang.in (gtfiles): Add jcf.h.
+ * constants.c (find_tree_constant): New.
+ (set_constant_entry): Allocate cpool subfields using GGC. Update
+ for new cpool_entry type.
+ (find_constant1): Update for new cpool_entry type.
+ (find_constant2): Likewise.
+ (find_utf8_constant): Use find_tree_constant.
+ (find_class_or_string_constant): Remove unnecessary cast to jword.
+ Update for new cpool_entry type.
+ (count_constant_pool_bytes): Update for new cpool_entry type.
+ (write_constant_pool): Likewise.
+ (alloc_name_constant): Use find_tree_constant.
+ (build_constants_constructor): Update for new cpool_entry type.
+
+ 2002-08-08 Geoffrey Keating <geoffk@redhat.com>
+
+ * parse.y (mark_parser_ctxt): Delete.
+ (goal): Don't use ggc_add_root.
+ (create_new_parser_context): Use GC to allocate struct parser_ctxt.
+ (java_pop_parser_context): Let GC free parser_ctxt.
+ (java_parser_context_resume): Likewise.
+ * parse.h (struct parser_ctxt): Use gengtype to mark.
+ (ctxp): Likewise.
+ (ctxp_for_generation): Likewise.
+ * lex.h (struct java_lc_s): Mark for gengtype.
+ (java_lexer): Rearrange for gengtype.
+ * config-lang.in (gtfiles): Add lex.h, parse.h.
+
2003-01-09 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* All Files: Remove PARAMS macro.
diff --git a/gcc/java/Make-lang.in b/gcc/java/Make-lang.in
index b04a975630e..bd839d6a354 100644
--- a/gcc/java/Make-lang.in
+++ b/gcc/java/Make-lang.in
@@ -113,12 +113,12 @@ JAVA_OBJS = java/parse.o java/class.o java/decl.o java/expr.o \
java/jcf-path.o java/xref.o java/boehm.o java/java-tree-inline.o mkdeps.o
GCJH_OBJS = java/gjavah.o java/jcf-io.o java/jcf-depend.o java/jcf-path.o \
- java/zextract.o version.o mkdeps.o errors.o
+ java/zextract.o version.o mkdeps.o errors.o ggc-none.o
JVSCAN_OBJS = java/parse-scan.o java/jv-scan.o version.o
JCFDUMP_OBJS = java/jcf-dump.o java/jcf-io.o java/jcf-depend.o java/jcf-path.o \
- java/zextract.o errors.o version.o mkdeps.o
+ java/zextract.o errors.o version.o mkdeps.o ggc-none.o
JVGENMAIN_OBJS = java/jvgenmain.o java/mangle_name.o errors.o
@@ -267,9 +267,9 @@ java/parse.o: java/parse.c java/jcf-reader.c $(CONFIG_H) $(SYSTEM_H) \
java/lex.h $(GGC_H) debug.h gt-java-parse.h gtype-java.h
java/jcf-dump.o: $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(JAVA_TREE_H) \
java/jcf-dump.c java/jcf-reader.c java/jcf.h java/javaop.h java/javaop.def \
- version.h
+ version.h $(GGC_H)
java/gjavah.o: $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(JAVA_TREE_H) \
- java/gjavah.c java/jcf-reader.c java/jcf.h java/javaop.h version.h
+ java/gjavah.c java/jcf-reader.c java/jcf.h java/javaop.h version.h $(GGC_H)
java/boehm.o: java/boehm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) $(JAVA_TREE_H) java/parse.h toplev.h
java/buffer.o: java/buffer.c $(CONFIG_H) java/buffer.h $(SYSTEM_H) coretypes.h \
diff --git a/gcc/java/config-lang.in b/gcc/java/config-lang.in
index 993763ed500..05a6fdff7e7 100644
--- a/gcc/java/config-lang.in
+++ b/gcc/java/config-lang.in
@@ -36,7 +36,7 @@ compilers="jc1\$(exeext) jvgenmain\$(exeext)"
stagestuff="jc1\$(exeext) gcj\$(exeext) jvgenmain\$(exeext) gcjh\$(exeext) jv-scan\$(exeext) jcf-dump\$(exeext)"
-gtfiles="\$(srcdir)/java/java-tree.h \$(srcdir)/java/builtins.c \$(srcdir)/java/class.c \$(srcdir)/java/constants.c \$(srcdir)/java/decl.c \$(srcdir)/java/expr.c \$(srcdir)/java/jcf-parse.c \$(srcdir)/java/jcf-write.c \$(srcdir)/java/lang.c \$(srcdir)/java/mangle.c \$(srcdir)/java/parse.y"
+gtfiles="\$(srcdir)/java/java-tree.h \$(srcdir)/java/jcf.h \$(srcdir)/java/lex.h \$(srcdir)/java/parse.h \$(srcdir)/java/builtins.c \$(srcdir)/java/class.c \$(srcdir)/java/constants.c \$(srcdir)/java/decl.c \$(srcdir)/java/expr.c \$(srcdir)/java/jcf-parse.c \$(srcdir)/java/jcf-write.c \$(srcdir)/java/lang.c \$(srcdir)/java/mangle.c \$(srcdir)/java/parse.y"
target_libs=${libgcj_saved}
lang_dirs="zlib fastjar"
diff --git a/gcc/java/constants.c b/gcc/java/constants.c
index 11efc2bf0c0..a1872387f18 100644
--- a/gcc/java/constants.c
+++ b/gcc/java/constants.c
@@ -32,6 +32,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */
#include "ggc.h"
static void set_constant_entry (CPool *, int, int, jword);
+static int find_tree_constant (CPool *, int, tree);
static int find_class_or_string_constant (CPool *, int, tree);
static int find_name_and_type_constant (CPool *, tree, tree);
static tree get_tag_node (int);
@@ -49,8 +50,8 @@ set_constant_entry (cpool, index, tag, value)
if (cpool->data == NULL)
{
cpool->capacity = 100;
- cpool->tags = xmalloc (sizeof(uint8) * cpool->capacity);
- cpool->data = xmalloc (sizeof(jword) * cpool->capacity);
+ cpool->tags = ggc_alloc (sizeof(uint8) * cpool->capacity);
+ cpool->data = ggc_alloc (sizeof(union cpool_entry) * cpool->capacity);
cpool->count = 1;
}
if (index >= cpool->capacity)
@@ -58,13 +59,15 @@ set_constant_entry (cpool, index, tag, value)
cpool->capacity *= 2;
if (index >= cpool->capacity)
cpool->capacity = index + 10;
- cpool->tags = xrealloc (cpool->tags, sizeof(uint8) * cpool->capacity);
- cpool->data = xrealloc (cpool->data, sizeof(jword) * cpool->capacity);
+ cpool->tags = ggc_realloc (cpool->tags,
+ sizeof(uint8) * cpool->capacity);
+ cpool->data = ggc_realloc (cpool->data,
+ sizeof(union cpool_entry) * cpool->capacity);
}
if (index >= cpool->count)
cpool->count = index + 1;
cpool->tags[index] = tag;
- cpool->data[index] = value;
+ cpool->data[index].w = value;
}
/* Find (or create) a constant pool entry matching TAG and VALUE. */
@@ -78,7 +81,7 @@ find_constant1 (cpool, tag, value)
int i;
for (i = cpool->count; --i > 0; )
{
- if (cpool->tags[i] == tag && cpool->data[i] == value)
+ if (cpool->tags[i] == tag && cpool->data[i].w == value)
return i;
}
i = cpool->count == 0 ? 1 : cpool->count;
@@ -98,8 +101,8 @@ find_constant2 (cpool, tag, word1, word2)
for (i = cpool->count - 1; --i > 0; )
{
if (cpool->tags[i] == tag
- && cpool->data[i] == word1
- && cpool->data[i+1] == word2)
+ && cpool->data[i].w == word1
+ && cpool->data[i+1].w == word2)
return i;
}
i = cpool->count == 0 ? 1 : cpool->count;
@@ -108,6 +111,25 @@ find_constant2 (cpool, tag, word1, word2)
return i;
}
+static int
+find_tree_constant (cpool, tag, value)
+ CPool *cpool;
+ int tag;
+ tree value;
+{
+ int i;
+ for (i = cpool->count; --i > 0; )
+ {
+ if (cpool->tags[i] == tag && cpool->data[i].t == value)
+ return i;
+ }
+ i = cpool->count == 0 ? 1 : cpool->count;
+ set_constant_entry (cpool, i, tag, 0);
+ cpool->data[i].t = value;
+ return i;
+}
+
+
int
find_utf8_constant (cpool, name)
CPool *cpool;
@@ -115,7 +137,7 @@ find_utf8_constant (cpool, name)
{
if (name == NULL_TREE)
return 0;
- return find_constant1 (cpool, CONSTANT_Utf8, (jword) name);
+ return find_tree_constant (cpool, CONSTANT_Utf8, name);
}
static int
@@ -124,15 +146,15 @@ find_class_or_string_constant (cpool, tag, name)
int tag;
tree name;
{
- int j = find_utf8_constant (cpool, name);
+ jword j = find_utf8_constant (cpool, name);
int i;
for (i = cpool->count; --i > 0; )
{
- if (cpool->tags[i] == tag && cpool->data[i] == (jword) j)
+ if (cpool->tags[i] == tag && cpool->data[i].w == j)
return i;
}
i = cpool->count;
- set_constant_entry (cpool, i, tag, (jword) j);
+ set_constant_entry (cpool, i, tag, j);
return i;
}
@@ -255,7 +277,7 @@ count_constant_pool_bytes (cpool)
break;
case CONSTANT_Utf8:
{
- tree t = (tree) cpool->data[i];
+ tree t = cpool->data[i].t;
int len = IDENTIFIER_LENGTH (t);
size += len + 2;
}
@@ -279,7 +301,7 @@ write_constant_pool (cpool, buffer, length)
{
unsigned char *ptr = buffer;
int i = 1;
- jword *datap = &cpool->data[1];
+ union cpool_entry *datap = &cpool->data[1];
PUT2 (cpool->count);
for ( ; i < cpool->count; i++, datap++)
{
@@ -293,23 +315,23 @@ write_constant_pool (cpool, buffer, length)
case CONSTANT_InterfaceMethodref:
case CONSTANT_Float:
case CONSTANT_Integer:
- PUT4 (*datap);
+ PUT4 (datap->w);
break;
case CONSTANT_Class:
case CONSTANT_String:
- PUT2 (*datap);
+ PUT2 (datap->w);
break;
break;
case CONSTANT_Long:
case CONSTANT_Double:
- PUT4(*datap);
+ PUT4(datap->w);
i++;
datap++;
- PUT4 (*datap);
+ PUT4 (datap->w);
break;
case CONSTANT_Utf8:
{
- tree t = (tree) *datap;
+ tree t = datap->t;
int len = IDENTIFIER_LENGTH (t);
PUT2 (len);
PUTN (IDENTIFIER_POINTER (t), len);
@@ -347,7 +369,7 @@ alloc_name_constant (tag, name)
int tag;
tree name;
{
- return find_constant1 (outgoing_cpool, tag, (jword) name);
+ return find_tree_constant (outgoing_cpool, tag, name);
}
/* Build an identifier for the internal name of reference type TYPE. */
@@ -438,7 +460,7 @@ build_constants_constructor ()
= tree_cons (NULL_TREE, get_tag_node (outgoing_cpool->tags[i]),
tags_list);
data_list
- = tree_cons (NULL_TREE, build_utf8_ref ((tree)outgoing_cpool->data[i]),
+ = tree_cons (NULL_TREE, build_utf8_ref (outgoing_cpool->data[i].t),
data_list);
}
if (outgoing_cpool->count > 0)
diff --git a/gcc/java/gjavah.c b/gcc/java/gjavah.c
index 45509977cde..0c333137c56 100644
--- a/gcc/java/gjavah.c
+++ b/gcc/java/gjavah.c
@@ -38,6 +38,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */
#include "javaop.h"
#include "java-tree.h"
#include "java-opcodes.h"
+#include "ggc.h"
#include "hashtab.h"
#include <getopt.h>
diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h
index b4ed394eec7..9a79f3e36b4 100644
--- a/gcc/java/java-tree.h
+++ b/gcc/java/java-tree.h
@@ -229,7 +229,7 @@ extern int flag_store_check;
extern const char *current_encoding;
/* The Java .class file that provides main_class; the main input file. */
-extern struct JCF *current_jcf;
+extern GTY(()) struct JCF * current_jcf;
typedef struct CPool constant_pool;
@@ -241,7 +241,7 @@ typedef struct CPool constant_pool;
/* The cpool->data[i] for a ResolvedClass points to a RECORD_TYPE. */
#define CONSTANT_ResolvedClass (CONSTANT_Class+CONSTANT_ResolvedFlag)
-#define CPOOL_UTF(CPOOL, INDEX) ((tree) (CPOOL)->data[INDEX])
+#define CPOOL_UTF(CPOOL, INDEX) ((CPOOL)->data[INDEX].t)
/* A NameAndType constant is represented as a TREE_LIST.
The type is the signature string (as an IDENTIFIER_NODE). */
@@ -686,7 +686,7 @@ extern GTY(()) tree java_global_trees[JTI_MAX];
#define nativecode_ptr_type_node ptr_type_node
/* They need to be reset before processing each class */
-extern struct CPool *outgoing_cpool;
+extern GTY(()) struct CPool *outgoing_cpool;
#define wfl_operator \
java_global_trees[JTI_WFL_OPERATOR]
@@ -1066,8 +1066,8 @@ struct lang_decl GTY(())
struct lang_type GTY(())
{
tree signature;
- struct JCF * GTY ((skip (""))) jcf;
- struct CPool * GTY ((skip (""))) cpool;
+ struct JCF * jcf;
+ struct CPool * cpool;
tree cpool_data_ref; /* Cached */
tree finit_stmt_list; /* List of statements finit$ will use */
tree clinit_stmt_list; /* List of statements <clinit> will use */
diff --git a/gcc/java/jcf-dump.c b/gcc/java/jcf-dump.c
index e780b8430bf..a5de5c57cb5 100644
--- a/gcc/java/jcf-dump.c
+++ b/gcc/java/jcf-dump.c
@@ -53,6 +53,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */
#include "system.h"
#include "coretypes.h"
#include "tm.h"
+#include "ggc.h"
#include "jcf.h"
#include "tree.h"
diff --git a/gcc/java/jcf-parse.c b/gcc/java/jcf-parse.c
index 93798261b3a..cd2c1cf819f 100644
--- a/gcc/java/jcf-parse.c
+++ b/gcc/java/jcf-parse.c
@@ -62,7 +62,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */
text = (JCF)->read_ptr; \
save = text[LENGTH]; \
text[LENGTH] = 0; \
- (JCF)->cpool.data[INDEX] = (jword) get_identifier (text); \
+ (JCF)->cpool.data[INDEX].t = get_identifier (text); \
text[LENGTH] = save; \
JCF_SKIP (JCF, LENGTH); } while (0)
@@ -86,7 +86,7 @@ static GTY(()) tree parse_roots[3];
#define current_file_list parse_roots[2]
/* The Java archive that provides main_class; the main input file. */
-static struct JCF main_jcf[1];
+static GTY(()) struct JCF * main_jcf;
static struct ZipFile *localToFile;
@@ -100,33 +100,9 @@ static void parse_source_file_2 (void);
static void parse_source_file_3 (void);
static void parse_class_file (void);
static void set_source_filename (JCF *, int);
-static void ggc_mark_jcf (void**);
static void jcf_parse (struct JCF*);
static void load_inner_classes (tree);
-/* Mark (for garbage collection) all the tree nodes that are
- referenced from JCF's constant pool table. Do that only if the JCF
- hasn't been marked finished. */
-
-static void
-ggc_mark_jcf (elt)
- void **elt;
-{
- JCF *jcf = *(JCF**) elt;
- if (jcf != NULL && !jcf->finished)
- {
- CPool *cpool = &jcf->cpool;
- int size = CPOOL_COUNT(cpool);
- int index;
- for (index = 1; index < size; index++)
- {
- int tag = JPOOL_TAG (jcf, index);
- if ((tag & CONSTANT_ResolvedFlag) || tag == CONSTANT_Utf8)
- ggc_mark_tree ((tree) cpool->data[index]);
- }
- }
-}
-
/* Handle "SourceFile" attribute. */
static void
@@ -270,7 +246,7 @@ get_constant (jcf, index)
goto bad;
tag = JPOOL_TAG (jcf, index);
if ((tag & CONSTANT_ResolvedFlag) || tag == CONSTANT_Utf8)
- return (tree) jcf->cpool.data[index];
+ return jcf->cpool.data[index].t;
switch (tag)
{
case CONSTANT_Integer:
@@ -352,7 +328,7 @@ get_constant (jcf, index)
goto bad;
}
JPOOL_TAG (jcf, index) = tag | CONSTANT_ResolvedFlag;
- jcf->cpool.data [index] = (jword) value;
+ jcf->cpool.data[index].t = value;
return value;
bad:
internal_error ("bad value constant type %d, index %d",
@@ -435,7 +411,7 @@ give_name_to_class (jcf, i)
if (main_input_filename == NULL && jcf == main_jcf)
main_input_filename = input_filename;
- jcf->cpool.data[i] = (jword) this_class;
+ jcf->cpool.data[i].t = this_class;
JPOOL_TAG (jcf, i) = CONSTANT_ResolvedClass;
return this_class;
}
@@ -465,11 +441,11 @@ get_class_constant (JCF *jcf , int i)
tree cname = unmangle_classname (name, nlength);
type = lookup_class (cname);
}
- jcf->cpool.data[i] = (jword) type;
+ jcf->cpool.data[i].t = type;
JPOOL_TAG (jcf, i) = CONSTANT_ResolvedClass;
}
else
- type = (tree) jcf->cpool.data[i];
+ type = jcf->cpool.data[i].t;
return type;
}
@@ -709,8 +685,7 @@ load_inner_classes (cur_class)
void
init_outgoing_cpool ()
{
- outgoing_cpool = xmalloc (sizeof (struct CPool));
- memset (outgoing_cpool, 0, sizeof (struct CPool));
+ outgoing_cpool = ggc_alloc_cleared (sizeof (struct CPool));
}
static void
@@ -1074,7 +1049,7 @@ java_parse_file (set_yydebug)
if (magic == 0xcafebabe)
{
CLASS_FILE_P (node) = 1;
- current_jcf = ALLOC (sizeof (JCF));
+ current_jcf = ggc_alloc (sizeof (JCF));
JCF_ZERO (current_jcf);
current_jcf->read_state = finput;
current_jcf->filbuf = jcf_filbuf_from_stdio;
@@ -1086,6 +1061,7 @@ java_parse_file (set_yydebug)
else if (magic == (JCF_u4)ZIPMAGIC)
{
ZIP_FILE_P (node) = 1;
+ main_jcf = ggc_alloc (sizeof (JCF));
JCF_ZERO (main_jcf);
main_jcf->read_state = finput;
main_jcf->filbuf = jcf_filbuf_from_stdio;
@@ -1223,7 +1199,7 @@ process_zip_dir (FILE *finput)
class_name = ALLOC (zdir->filename_length+1-6);
file_name = ALLOC (zdir->filename_length+1);
- jcf = ALLOC (sizeof (JCF));
+ jcf = ggc_alloc (sizeof (JCF));
JCF_ZERO (jcf);
strncpy (class_name, class_name_in_zip_dir, zdir->filename_length-6);
@@ -1255,9 +1231,6 @@ process_zip_dir (FILE *finput)
void
init_jcf_parse ()
{
- /* Register roots with the garbage collector. */
- ggc_add_root (&current_jcf, 1, sizeof (JCF), (void (*)(void *))ggc_mark_jcf);
-
init_src_parse ();
}
diff --git a/gcc/java/jcf-reader.c b/gcc/java/jcf-reader.c
index 1bd5299e97a..da45cc92ee6 100644
--- a/gcc/java/jcf-reader.c
+++ b/gcc/java/jcf-reader.c
@@ -264,8 +264,8 @@ jcf_parse_constant_pool (JCF* jcf)
{
int i, n;
JPOOL_SIZE (jcf) = (JCF_FILL (jcf, 2), JCF_readu2 (jcf));
- jcf->cpool.tags = ALLOC (JPOOL_SIZE (jcf));
- jcf->cpool.data = ALLOC (sizeof (jword) * JPOOL_SIZE (jcf));
+ jcf->cpool.tags = ggc_alloc (JPOOL_SIZE (jcf));
+ jcf->cpool.data = ggc_alloc (sizeof (jword) * JPOOL_SIZE (jcf));
jcf->cpool.tags[0] = 0;
#ifdef HANDLE_START_CONSTANT_POOL
HANDLE_START_CONSTANT_POOL (JPOOL_SIZE (jcf));
@@ -285,25 +285,25 @@ jcf_parse_constant_pool (JCF* jcf)
{
case CONSTANT_String:
case CONSTANT_Class:
- jcf->cpool.data[i] = JCF_readu2 (jcf);
+ jcf->cpool.data[i].w = JCF_readu2 (jcf);
break;
case CONSTANT_Fieldref:
case CONSTANT_Methodref:
case CONSTANT_InterfaceMethodref:
case CONSTANT_NameAndType:
- jcf->cpool.data[i] = JCF_readu2 (jcf);
- jcf->cpool.data[i] |= JCF_readu2 (jcf) << 16;
+ jcf->cpool.data[i].w = JCF_readu2 (jcf);
+ jcf->cpool.data[i].w |= JCF_readu2 (jcf) << 16;
break;
case CONSTANT_Integer:
case CONSTANT_Float:
- jcf->cpool.data[i] = JCF_readu4 (jcf);
+ jcf->cpool.data[i].w = JCF_readu4 (jcf);
break;
case CONSTANT_Long:
case CONSTANT_Double:
- jcf->cpool.data[i] = JCF_readu4 (jcf);
+ jcf->cpool.data[i].w = JCF_readu4 (jcf);
i++; /* These take up two spots in the constant pool */
jcf->cpool.tags[i] = 0;
- jcf->cpool.data[i] = JCF_readu4 (jcf);
+ jcf->cpool.data[i].w = JCF_readu4 (jcf);
break;
case CONSTANT_Utf8:
n = JCF_readu2 (jcf);
@@ -311,7 +311,7 @@ jcf_parse_constant_pool (JCF* jcf)
#ifdef HANDLE_CONSTANT_Utf8
HANDLE_CONSTANT_Utf8(jcf, i, n);
#else
- jcf->cpool.data[i] = JCF_TELL(jcf) - 2;
+ jcf->cpool.data[i].w = JCF_TELL(jcf) - 2;
JCF_SKIP (jcf, n);
#endif
break;
diff --git a/gcc/java/jcf.h b/gcc/java/jcf.h
index 0555f362372..c8e6aa7a602 100644
--- a/gcc/java/jcf.h
+++ b/gcc/java/jcf.h
@@ -55,9 +55,17 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */
#endif
struct JCF;
-typedef int (*jcf_filbuf_t) (struct JCF*, int needed);
+typedef int (*jcf_filbuf_t) PARAMS ((struct JCF*, int needed));
-typedef struct CPool {
+union cpool_entry GTY(()) {
+ jword GTY ((tag ("0"))) w;
+ tree GTY ((tag ("1"))) t;
+};
+
+#define cpool_entry_is_tree(tag) \
+ (tag & CONSTANT_ResolvedFlag) || tag == CONSTANT_Utf8
+
+typedef struct CPool GTY(()) {
/* Available number of elements in the constants array, before it
must be re-allocated. */
int capacity;
@@ -65,29 +73,33 @@ typedef struct CPool {
/* The constant_pool_count. */
int count;
- uint8* tags;
+ uint8* GTY((length ("%h.count"))) tags;
- jword* data;
+ union cpool_entry * GTY((length ("%h.count"),
+ desc ("cpool_entry_is_tree (%1.tags%a)"))) data;
} CPool;
struct ZipDirectory;
/* JCF encapsulates the state of reading a Java Class File. */
-typedef struct JCF {
- unsigned char *buffer;
- unsigned char *buffer_end;
- unsigned char *read_ptr;
- unsigned char *read_end;
+typedef struct JCF GTY(()) {
+ unsigned char * GTY ((skip (""))) buffer;
+ unsigned char * GTY ((skip (""))) buffer_end;
+ unsigned char * GTY ((skip (""))) read_ptr;
+ unsigned char * GTY ((skip (""))) read_end;
int java_source : 1;
int right_zip : 1;
int finished : 1;
jcf_filbuf_t filbuf;
- void *read_state;
+ PTR GTY ((skip (""))) read_state;
const char *filename;
const char *classname;
- struct ZipDirectory *zipd; /* Directory entry where it was found */
- JCF_u2 access_flags, this_class, super_class;
+ /* Directory entry where it was found. */
+ struct ZipDirectory * GTY ((skip (""))) zipd;
+ JCF_u2 access_flags;
+ JCF_u2 this_class;
+ JCF_u2 super_class;
CPool cpool;
} JCF;
/*typedef JCF* JCF_FILE;*/
@@ -102,13 +114,13 @@ typedef struct JCF {
#define JPOOL_SIZE(JCF) CPOOL_COUNT(&(JCF)->cpool)
#define JPOOL_TAG(JCF, INDEX) ((JCF)->cpool.tags[INDEX])
/* The INDEX'th constant pool entry as a JCF_u4. */
-#define CPOOL_UINT(CPOOL, INDEX) ((CPOOL)->data[INDEX])
+#define CPOOL_UINT(CPOOL, INDEX) ((CPOOL)->data[INDEX].w)
#define JPOOL_UINT(JCF, INDEX) CPOOL_UINT(&(JCF)->cpool, INDEX) /*deprecated*/
/* The first uint16 of the INDEX'th constant pool entry. */
-#define CPOOL_USHORT1(CPOOL, INDEX) ((CPOOL)->data[INDEX] & 0xFFFF)
+#define CPOOL_USHORT1(CPOOL, INDEX) ((CPOOL)->data[INDEX].w & 0xFFFF)
#define JPOOL_USHORT1(JCF, INDEX) CPOOL_USHORT1(&(JCF)->cpool, INDEX)
/* The second uint16 of the INDEX'th constant pool entry. */
-#define CPOOL_USHORT2(CPOOL, INDEX) ((CPOOL)->data[INDEX] >> 16)
+#define CPOOL_USHORT2(CPOOL, INDEX) ((CPOOL)->data[INDEX].w >> 16)
#define JPOOL_USHORT2(JCF, INDEX) CPOOL_USHORT2(&(JCF)->cpool, INDEX)
#define JPOOL_LONG(JCF, INDEX) \
WORDS_TO_LONG (JPOOL_UINT(JCF, INDEX), JPOOL_UINT(JCF, (INDEX)+1))
@@ -128,9 +140,10 @@ typedef struct JCF {
#define CPOOL_INDEX_IN_RANGE(CPOOL, INDEX) \
((INDEX) > 0 && (INDEX) < CPOOL_COUNT(CPOOL))
-#define CPOOL_FINISH(CPOOL) { \
- if ((CPOOL)->tags) FREE ((CPOOL)->tags); \
- if ((CPOOL)->data) FREE ((CPOOL)->data); }
+#define CPOOL_FINISH(CPOOL) { \
+ (CPOOL)->tags = 0; \
+ (CPOOL)->data = 0; \
+ }
#define JCF_FINISH(JCF) { \
CPOOL_FINISH(&(JCF)->cpool); \
diff --git a/gcc/java/lex.c b/gcc/java/lex.c
index c6744f401e7..976d0cf08af 100644
--- a/gcc/java/lex.c
+++ b/gcc/java/lex.c
@@ -125,7 +125,7 @@ java_init_lex (finput, encoding)
CPC_INSTANCE_INITIALIZER_LIST (ctxp) = NULL_TREE;
memset (ctxp->modifier_ctx, 0, sizeof (ctxp->modifier_ctx));
- memset (current_jcf, 0, sizeof (JCF));
+ current_jcf = ggc_alloc_cleared (sizeof (JCF));
ctxp->current_parsed_class = NULL;
ctxp->package = NULL_TREE;
#endif
diff --git a/gcc/java/lex.h b/gcc/java/lex.h
index 9579036c602..aa9a2beea34 100644
--- a/gcc/java/lex.h
+++ b/gcc/java/lex.h
@@ -96,13 +96,13 @@ struct java_error {
int error;
};
-typedef struct _java_lc {
+typedef struct java_lc_s GTY(()) {
int line;
int prev_col;
int col;
} java_lc;
-typedef struct java_lexer
+struct java_lexer
{
/* The file from which we're reading. */
FILE *finput;
@@ -155,7 +155,8 @@ typedef struct java_lexer
int out_last;
#endif /* HAVE_ICONV */
-} java_lexer;
+};
+typedef struct java_lexer java_lexer;
/* Destroy a lexer object. */
extern void java_destroy_lexer (java_lexer *);
diff --git a/gcc/java/parse.h b/gcc/java/parse.h
index 37731fbd255..a6681afd6f0 100644
--- a/gcc/java/parse.h
+++ b/gcc/java/parse.h
@@ -427,9 +427,6 @@ enum {
INVOKE_VIRTUAL
};
-/* We need the resolution stuff only if we compile jc1 */
-#ifndef JC1_LITE
-
/* Unresolved type identifiers handling. When we process the source
code, we blindly accept an unknown type identifier and try to
resolve it later. When an unknown type identifier is encountered
@@ -509,13 +506,12 @@ typedef struct _jdep {
#define JDEP_RESOLVED_P(J) \
(!(J)->solv || TREE_CODE ((J)->solv) != POINTER_TYPE)
-typedef struct _jdeplist {
+struct jdeplist_s {
jdep *first;
jdep *last;
- struct _jdeplist *next;
-} jdeplist;
-
-#endif /* JC1_LITE */
+ struct jdeplist_s *next;
+};
+typedef struct jdeplist_s jdeplist;
#define CLASSD_FIRST(CD) ((CD)->first)
#define CLASSD_LAST(CD) ((CD)->last)
@@ -727,14 +723,15 @@ typedef struct _jdeplist {
#define DECL_INHERITED_SOURCE_LINE(DECL) (DECL_CHECK (DECL)->decl.u2.i)
/* Parser context data structure. */
-struct parser_ctxt {
+struct parser_ctxt GTY(()) {
const char *filename; /* Current filename */
struct parser_ctxt *next;
- java_lexer *lexer; /* Current lexer state */
+ java_lexer * GTY((skip (""))) lexer; /* Current lexer state */
char marker_begining; /* Marker. Should be a sub-struct */
- struct java_line *p_line, *c_line; /* Previous and current line */
+ struct java_line * GTY ((skip (""))) p_line; /* Previous line */
+ struct java_line * GTY ((skip (""))) c_line; /* Current line */
java_lc elc; /* Error's line column info */
int ccb_indent; /* Keep track of {} indent, lexer */
int first_ccb_indent1; /* First { at ident level 1 */
@@ -742,7 +739,7 @@ struct parser_ctxt {
int parser_ccb_indent; /* Keep track of {} indent, parser */
int osb_depth; /* Current depth of [ in an expression */
int osb_limit; /* Limit of this depth */
- int *osb_number; /* Keep track of ['s */
+ int * GTY ((skip (""))) osb_number; /* Keep track of ['s */
int lineno; /* Current lineno */
char marker_end; /* End marker. Should be a sub-struct */
@@ -761,13 +758,12 @@ struct parser_ctxt {
/* Flag to report certain errors (fix this documentation. FIXME) */
unsigned class_err:1;
- /* This section is defined only if we compile jc1 */
-#ifndef JC1_LITE
+ /* This section is used only if we compile jc1 */
tree modifier_ctx [12]; /* WFL of modifiers */
tree class_type; /* Current class */
tree function_decl; /* Current function decl, save/restore */
- struct JCF *current_jcf; /* CU jcf */
+ struct JCF * current_jcf; /* CU jcf */
int prevent_ese; /* Prevent expression statement error */
@@ -778,7 +774,7 @@ struct parser_ctxt {
/* These two lists won't survive file traversal */
tree class_list; /* List of classes in a CU */
- jdeplist *classd_list; /* Classe dependencies in a CU */
+ jdeplist * GTY((skip (""))) classd_list; /* Classe dependencies in a CU */
tree current_parsed_class; /* Class currently parsed */
tree current_parsed_class_un; /* Curr. parsed class unqualified name */
@@ -801,7 +797,6 @@ struct parser_ctxt {
constructor. This flag is used to trap
illegal argument usage during an
explicit constructor invocation. */
-#endif /* JC1_LITE */
};
/* A set of macros to push/pop/access the currently parsed class. */
@@ -947,7 +942,7 @@ ATTRIBUTE_NORETURN
;
extern void java_expand_classes (void);
-extern struct parser_ctxt *ctxp;
-extern struct parser_ctxt *ctxp_for_generation;
+extern GTY(()) struct parser_ctxt *ctxp;
+extern GTY(()) struct parser_ctxt *ctxp_for_generation;
#endif /* ! GCC_JAVA_PARSE_H */
diff --git a/gcc/java/parse.y b/gcc/java/parse.y
index 3dbe3b3ed3a..c67a42e11f6 100644
--- a/gcc/java/parse.y
+++ b/gcc/java/parse.y
@@ -304,13 +304,16 @@ static tree maybe_build_thisn_access_method (tree);
static tree build_outer_field_access (tree, tree);
static tree build_outer_field_access_methods (tree);
-static tree build_outer_field_access_expr (int, tree, tree, tree, tree);
+static tree build_outer_field_access_expr (int, tree, tree,
+ tree, tree);
static tree build_outer_method_access_method (tree);
static tree build_new_access_id (void);
-static tree build_outer_field_access_method (tree, tree, tree, tree, tree);
+static tree build_outer_field_access_method (tree, tree, tree,
+ tree, tree);
static int outer_field_access_p (tree, tree);
-static int outer_field_expanded_access_p (tree, tree *, tree *, tree *);
+static int outer_field_expanded_access_p (tree, tree *,
+ tree *, tree *);
static tree outer_field_access_fix (tree, tree, tree);
static tree build_incomplete_class_ref (int, tree);
static tree patch_incomplete_class_ref (tree);
@@ -321,7 +324,6 @@ static void add_inner_class_fields (tree, tree);
static tree build_dot_class_method (tree);
static tree build_dot_class_method_invocation (tree);
static void create_new_parser_context (int);
-static void mark_parser_ctxt (void *);
static tree maybe_build_class_init_for_field (tree, tree);
static int attach_init_test_initialization_flags (PTR *, PTR);
@@ -594,18 +596,7 @@ static GTY(()) tree src_parse_roots[1];
%%
/* 19.2 Production from 2.3: The Syntactic Grammar */
-goal:
- {
- /* Register static variables with the garbage
- collector. */
- ggc_add_root (&ctxp, 1,
- sizeof (struct parser_ctxt *),
- mark_parser_ctxt);
- ggc_add_root (&ctxp_for_generation, 1,
- sizeof (struct parser_ctxt *),
- mark_parser_ctxt);
- }
- compilation_unit
+goal: compilation_unit
{}
;
@@ -2669,7 +2660,7 @@ create_new_parser_context (copy_from_previous)
{
struct parser_ctxt *new;
- new = (struct parser_ctxt *)xmalloc(sizeof (struct parser_ctxt));
+ new = (struct parser_ctxt *) ggc_alloc (sizeof (struct parser_ctxt));
if (copy_from_previous)
{
memcpy ((PTR)new, (PTR)ctxp, sizeof (struct parser_ctxt));
@@ -2730,8 +2721,6 @@ java_pop_parser_context (generate)
toFree->next = ctxp_for_generation;
ctxp_for_generation = toFree;
}
- else
- free (toFree);
}
/* Create a parser context for the use of saving some global
@@ -2830,10 +2819,6 @@ java_parser_context_resume ()
/* Re-installed the data for the parsing to carry on */
memcpy (&ctxp->marker_begining, &old->marker_begining,
(size_t)(&ctxp->marker_end - &ctxp->marker_begining));
-
- /* Buffer context can now be discarded */
- free (saver);
- free (old);
}
/* Add a new anchor node to which all statement(s) initializing static
@@ -6732,10 +6717,9 @@ process_imports ()
tree to_be_found = EXPR_WFL_NODE (TREE_PURPOSE (import));
char *original_name;
- obstack_grow0 (&temporary_obstack,
- IDENTIFIER_POINTER (to_be_found),
- IDENTIFIER_LENGTH (to_be_found));
- original_name = obstack_finish (&temporary_obstack);
+ original_name = xmemdup (IDENTIFIER_POINTER (to_be_found),
+ IDENTIFIER_LENGTH (to_be_found),
+ IDENTIFIER_LENGTH (to_be_found) + 1);
/* Don't load twice something already defined. */
if (IDENTIFIER_CLASS_VALUE (to_be_found))
@@ -6771,7 +6755,7 @@ process_imports ()
error_found = 1;
}
- obstack_free (&temporary_obstack, original_name);
+ free (original_name);
if (error_found)
return 1;
}
@@ -16190,42 +16174,6 @@ resolve_qualified_name (name, context)
}
#endif
-/* Mark P, which is really a `struct parser_ctxt **' for GC. */
-
-static void
-mark_parser_ctxt (p)
- void *p;
-{
- struct parser_ctxt *pc = *((struct parser_ctxt **) p);
-#ifndef JC1_LITE
- size_t i;
-#endif
-
- if (!pc)
- return;
-
-#ifndef JC1_LITE
- for (i = 0; i < ARRAY_SIZE (pc->modifier_ctx); ++i)
- ggc_mark_tree (pc->modifier_ctx[i]);
- ggc_mark_tree (pc->class_type);
- ggc_mark_tree (pc->function_decl);
- ggc_mark_tree (pc->package);
- ggc_mark_tree (pc->class_list);
- ggc_mark_tree (pc->current_parsed_class);
- ggc_mark_tree (pc->current_parsed_class_un);
- ggc_mark_tree (pc->non_static_initialized);
- ggc_mark_tree (pc->static_initialized);
- ggc_mark_tree (pc->instance_initializers);
- ggc_mark_tree (pc->import_list);
- ggc_mark_tree (pc->import_demand_list);
- ggc_mark_tree (pc->current_loop);
- ggc_mark_tree (pc->current_labeled_block);
-#endif /* JC1_LITE */
-
- if (pc->next)
- mark_parser_ctxt (&pc->next);
-}
-
void
init_src_parse ()
{
diff --git a/gcc/mkdeps.c b/gcc/mkdeps.c
index 26504e14afa..0c573cd4d82 100644
--- a/gcc/mkdeps.c
+++ b/gcc/mkdeps.c
@@ -291,3 +291,77 @@ deps_phony_targets (d, fp)
putc ('\n', fp);
}
}
+
+/* Write out a deps buffer to a file, in a form that can be read back
+ with deps_restore. Returns nonzero on error, in which case the
+ error number will be in errno. */
+
+int
+deps_save (deps, f)
+ struct deps *deps;
+ FILE *f;
+{
+ unsigned int i;
+
+ /* The cppreader structure contains makefile dependences. Write out this
+ structure. */
+
+ /* The number of dependences. */
+ if (fwrite (&deps->ndeps, sizeof (deps->ndeps), 1, f) != 1)
+ return -1;
+ /* The length of each dependence followed by the string. */
+ for (i = 0; i < deps->ndeps; i++)
+ {
+ size_t num_to_write = strlen (deps->depv[i]);
+ if (fwrite (&num_to_write, sizeof (size_t), 1, f) != 1)
+ return -1;
+ if (fwrite (deps->depv[i], num_to_write, 1, f) != 1)
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Read back dependency information written with deps_save into
+ the deps buffer. The third argument may be NULL, in which case
+ the dependency information is just skipped, or it may be a filename,
+ in which case that filename is skipped. */
+
+int
+deps_restore (deps, fd, self)
+ struct deps *deps;
+ FILE *fd;
+ const char *self;
+{
+ unsigned int i, count;
+ size_t num_to_read;
+ size_t buf_size = 512;
+ char *buf = (char *) xmalloc (buf_size);
+
+ /* Number of dependences. */
+ if (fread (&count, 1, sizeof (count), fd) != sizeof (count))
+ return -1;
+
+ /* The length of each dependence string, followed by the string. */
+ for (i = 0; i < count; i++)
+ {
+ /* Read in # bytes in string. */
+ if (fread (&num_to_read, 1, sizeof (size_t), fd) != sizeof (size_t))
+ return -1;
+ if (buf_size < num_to_read + 1)
+ {
+ buf_size = num_to_read + 1 + 127;
+ buf = xrealloc (buf, buf_size);
+ }
+ if (fread (buf, 1, num_to_read, fd) != num_to_read)
+ return -1;
+ buf[num_to_read] = '\0';
+
+ /* Generate makefile dependencies from .pch if -nopch-deps. */
+ if (self != NULL && strcmp (buf, self) != 0)
+ deps_add_dep (deps, buf);
+ }
+
+ free (buf);
+ return 0;
+}
diff --git a/gcc/mkdeps.h b/gcc/mkdeps.h
index fa79b86591b..2be8f81a99c 100644
--- a/gcc/mkdeps.h
+++ b/gcc/mkdeps.h
@@ -53,6 +53,17 @@ extern void deps_add_dep PARAMS ((struct deps *, const char *));
extern void deps_write PARAMS ((const struct deps *, FILE *,
unsigned int));
+/* Write out a deps buffer to a file, in a form that can be read back
+ with deps_restore. Returns nonzero on error, in which case the
+ error number will be in errno. */
+extern int deps_save PARAMS ((struct deps *, FILE *));
+
+/* Read back dependency information written with deps_save into
+ the deps buffer. The third argument may be NULL, in which case
+ the dependency information is just skipped, or it may be a filename,
+ in which case that filename is skipped. */
+extern int deps_restore PARAMS ((struct deps *, FILE *, const char *));
+
/* For each dependency *except the first*, emit a dummy rule for that
file, causing it to depend on nothing. This is used to work around
the intermediate-file deletion misfeature in Make, in some
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 3f0d3391d5e..3a5de01b2db 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -56,6 +56,7 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
#include "toplev.h"
#include "ggc.h"
+#include "varray.h"
#include "debug.h"
#include "target.h"
#include "diagnostic.h"
diff --git a/gcc/optabs.h b/gcc/optabs.h
index e3890fe9a90..2ff8fec62dd 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -1,5 +1,5 @@
/* Definitions for code generation pass of GNU compiler.
- Copyright (C) 2001 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
@@ -246,7 +246,7 @@ extern enum insn_code reload_in_optab[NUM_MACHINE_MODES];
extern enum insn_code reload_out_optab[NUM_MACHINE_MODES];
/* Contains the optab used for each rtx code. */
-extern optab code_to_optab[NUM_RTX_CODE + 1];
+extern GTY(()) optab code_to_optab[NUM_RTX_CODE + 1];
typedef rtx (*rtxfun) PARAMS ((rtx));
diff --git a/gcc/stringpool.c b/gcc/stringpool.c
index f3b34b139cf..1edb46f66a6 100644
--- a/gcc/stringpool.c
+++ b/gcc/stringpool.c
@@ -1,5 +1,5 @@
/* String pool for GCC.
- Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
@@ -50,7 +50,6 @@ static struct obstack string_stack;
static hashnode alloc_node PARAMS ((hash_table *));
static int mark_ident PARAMS ((struct cpp_reader *, hashnode, const PTR));
-static void mark_ident_hash PARAMS ((void *));
/* Initialize the string pool. */
void
@@ -60,7 +59,6 @@ init_stringpool ()
ident_hash = ht_create (14);
ident_hash->alloc_node = alloc_node;
gcc_obstack_init (&string_stack);
- ggc_add_root (&ident_hash, 1, sizeof ident_hash, mark_ident_hash);
}
/* Allocate a hash node. */
@@ -160,15 +158,94 @@ mark_ident (pfile, h, v)
hashnode h;
const PTR v ATTRIBUTE_UNUSED;
{
- ggc_mark_tree (HT_IDENT_TO_GCC_IDENT (h));
+ gt_ggc_m_9tree_node (HT_IDENT_TO_GCC_IDENT (h));
return 1;
}
-/* Mark all identifiers for GC. */
+/* Mark the trees hanging off the identifier node for GGC. These are
+ handled specially (not using gengtype) because of the special
+ treatment for strings. */
-static void
-mark_ident_hash (arg)
- PTR arg ATTRIBUTE_UNUSED;
+void
+ggc_mark_stringpool ()
{
ht_forall (ident_hash, mark_ident, NULL);
}
+
+/* Strings are _not_ GCed, but this routine exists so that a separate
+ roots table isn't needed for the few global variables that refer
+ to strings. */
+
+void
+gt_ggc_m_S (x)
+ void *x ATTRIBUTE_UNUSED;
+{
+}
+
+/* Pointer-walking routine for strings (not very interesting, since
+ strings don't contain pointers). */
+
+void
+gt_pch_p_S (obj, x, op, cookie)
+ void *obj ATTRIBUTE_UNUSED;
+ void *x ATTRIBUTE_UNUSED;
+ gt_pointer_operator op ATTRIBUTE_UNUSED;
+ void *cookie ATTRIBUTE_UNUSED;
+{
+}
+
+/* PCH pointer-walking routine for strings. */
+
+void
+gt_pch_n_S (x)
+ const void *x;
+{
+ gt_pch_note_object ((void *)x, (void *)x, &gt_pch_p_S);
+}
+
+/* Handle saving and restoring the string pool for PCH. */
+
+struct string_pool_data GTY(())
+{
+ tree * GTY((length ("%h.nslots"))) entries;
+ unsigned int nslots;
+ unsigned int nelements;
+};
+
+static GTY(()) struct string_pool_data * spd;
+
+void
+gt_pch_save_stringpool ()
+{
+ unsigned int i;
+
+ spd = ggc_alloc (sizeof (*spd));
+ spd->nslots = ident_hash->nslots;
+ spd->nelements = ident_hash->nelements;
+ spd->entries = ggc_alloc (sizeof (tree *) * spd->nslots);
+ for (i = 0; i < spd->nslots; i++)
+ if (ident_hash->entries[i] != NULL)
+ spd->entries[i] = HT_IDENT_TO_GCC_IDENT (ident_hash->entries[i]);
+ else
+ spd->entries[i] = NULL;
+}
+
+void
+gt_pch_restore_stringpool ()
+{
+ unsigned int i;
+
+ ident_hash->nslots = spd->nslots;
+ ident_hash->nelements = spd->nelements;
+ ident_hash->entries = xrealloc (ident_hash->entries,
+ sizeof (hashnode) * spd->nslots);
+ for (i = 0; i < spd->nslots; i++)
+ if (spd->entries[i] != NULL)
+ ident_hash->entries[i] = GCC_IDENT_TO_HT_IDENT (spd->entries[i]);
+ else
+ ident_hash->entries[i] = NULL;
+
+ spd = NULL;
+}
+
+#include "gt-stringpool.h"
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 8168b989ade..e1c6e0287ae 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,87 @@
+2003-01-09 Geoffrey Keating <geoffk@apple.com>
+
+ Merge from pch-branch:
+
+ 2002-12-23 Geoffrey Keating <geoffk@apple.com>
+
+ * gcc.dg/pch/cpp-1.h: New.
+ * gcc.dg/pch/cpp-1.c: New.
+ * gcc.dg/pch/cpp-2.h: New.
+ * gcc.dg/pch/cpp-2.c: New.
+
+ 2002-11-19 Geoffrey Keating <geoffk@apple.com>
+
+ * gcc.dg/pch/except-1.h: New.
+ * gcc.dg/pch/except-1.c: New.
+
+ 2002-11-13 Geoffrey Keating <geoffk@apple.com>
+
+ * gcc.dg/pch/pch.exp: Ensure that <test>.hp doesn't exist before
+ running test.
+ * gcc.dg/pch: Include *.hp not *.h.
+ * gcc.dg/pch/system-1.h: New.
+ * gcc.dg/pch/system-1.c: New.
+
+ 2002-11-11 Geoffrey Keating <geoffk@apple.com>
+
+ * gcc.dg/pch/pch.exp: Compare .s files with/without PCH,
+ rather than trying to build and run a program using PCH.
+ * gcc.dg/pch: Remove dg-do commands from test files.
+
+ 2002-11-08 Geoffrey Keating <geoffk@apple.com>
+
+ * gcc.dg/pch/macro-3.c: New.
+ * gcc.dg/pch/macro-3.h: New.
+
+ 2002-11-04 Geoffrey Keating <geoffk@apple.com>
+
+ * gcc.dg/pch/common-1.c: New.
+ * gcc.dg/pch/common-1.h: New.
+ * gcc.dg/pch/decl-1.c: New.
+ * gcc.dg/pch/decl-1.h: New.
+ * gcc.dg/pch/decl-2.c: New.
+ * gcc.dg/pch/decl-2.h: New.
+ * gcc.dg/pch/decl-3.c: New.
+ * gcc.dg/pch/decl-3.h: New.
+ * gcc.dg/pch/decl-4.c: New.
+ * gcc.dg/pch/decl-4.h: New.
+ * gcc.dg/pch/decl-5.c: New.
+ * gcc.dg/pch/decl-5.h: New.
+ * gcc.dg/pch/global-1.c: New.
+ * gcc.dg/pch/global-1.h: New.
+ * gcc.dg/pch/inline-1.c: New.
+ * gcc.dg/pch/inline-1.h: New.
+ * gcc.dg/pch/inline-2.c: New.
+ * gcc.dg/pch/inline-2.h: New.
+ * gcc.dg/pch/static-1.c: New.
+ * gcc.dg/pch/static-1.h: New.
+ * gcc.dg/pch/static-2.c: New.
+ * gcc.dg/pch/static-2.h: New.
+
+ 2002-09-01 Geoffrey Keating <geoffk@redhat.com>
+
+ * g++.dg/pch/pch.exp: Better handle failing testcases.
+ * gcc.dg/pch/pch.exp: Likewise.
+ * gcc.dg/pch/macro-1.c: New.
+ * gcc.dg/pch/macro-1.h: New.
+ * gcc.dg/pch/macro-2.c: New.
+ * gcc.dg/pch/macro-2.h: New.
+
+ 2002-08-27 Geoffrey Keating <geoffk@redhat.com>
+
+ * g++.dg/dg.exp: Treat files in pch/ specially.
+ * g++.dg/pch/pch.exp: New file.
+ * g++.dg/pch/empty.H: New file.
+ * g++.dg/pch/empty.C: New file.
+ * lib/g++-dg.exp (g++-dg-test): Add case for when $do_what is
+ "precompile".
+
+ * gcc.dg/pch/pch.exp: New file.
+ * gcc.dg/pch/empty.h: New file.
+ * gcc.dg/pch/empty.c: New file.
+ * lib/gcc-dg.exp (gcc-dg-test): Add case for when $do_what is
+ "precompile".
+
2003-01-09 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
* g++.dg/template/friend14.C: New test.
diff --git a/gcc/testsuite/g++.dg/dg.exp b/gcc/testsuite/g++.dg/dg.exp
index ea96197332f..d9839608733 100644
--- a/gcc/testsuite/g++.dg/dg.exp
+++ b/gcc/testsuite/g++.dg/dg.exp
@@ -35,6 +35,7 @@ set tests [prune $tests $srcdir/$subdir/bprob/*]
set tests [prune $tests $srcdir/$subdir/compat/*]
set tests [prune $tests $srcdir/$subdir/debug/*]
set tests [prune $tests $srcdir/$subdir/gcov/*]
+set tests [prune $tests $srcdir/$subdir/pch/*]
set tests [prune $tests $srcdir/$subdir/special/*]
set tests [prune $tests $srcdir/$subdir/tls/*]
diff --git a/gcc/testsuite/g++.dg/pch/empty.C b/gcc/testsuite/g++.dg/pch/empty.C
new file mode 100644
index 00000000000..7aef099f3ef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pch/empty.C
@@ -0,0 +1,5 @@
+#include "empty.Hp"
+int main()
+{
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/pch/empty.H b/gcc/testsuite/g++.dg/pch/empty.H
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pch/empty.H
diff --git a/gcc/testsuite/g++.dg/pch/pch.exp b/gcc/testsuite/g++.dg/pch/pch.exp
new file mode 100644
index 00000000000..8507e355f53
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pch/pch.exp
@@ -0,0 +1,100 @@
+# Copyright (C) 1997, 2002 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# GCC testsuite for precompiled header interaction,
+# that uses the `dg.exp' driver.
+
+# Load support procs.
+load_lib "g++-dg.exp"
+
+# Initialize `dg'.
+dg-init
+
+set old_dg_do_what_default "${dg-do-what-default}"
+
+# Main loop.
+foreach test [lsort [glob -nocomplain $srcdir/$subdir/*.C]] {
+ global runtests dg-do-what-default
+
+ # If we're only testing specific files and this isn't one of them, skip it.
+ if ![runtest_file_p $runtests $test] {
+ continue
+ }
+ set nshort [file tail [file dirname $test]]/[file tail $test]
+ set bname "[file rootname [file tail $test]]"
+
+ catch { file delete "$bname.Hp.pch" }
+ catch { file delete "$bname.H.pch" }
+ catch { file delete "$bname.s" }
+ catch { file delete "$bname.s-pch" }
+ catch { file delete "$bname.Hp" }
+
+ # We don't try to use the loop-optimizing options, since they are highly
+ # unlikely to make any difference to PCH.
+ foreach flags { "-g" "-O2 -g" "-O2" } {
+ verbose "Testing $nshort, $flags" 1
+
+ # For the header files, the default is to precompile.
+ set dg-do-what-default precompile
+ dg-test -keep-output "[file rootname $test].H" $flags ""
+
+ # For the rest, the default is to compile to .s.
+ set dg-do-what-default compile
+
+ if { [ file exists "$bname.H.pch" ] } {
+ # To ensure that the PCH is used, not the original header,
+ # the actual PCH file is renamed to "<foo>.Hp.pch".
+ file rename "$bname.H.pch" "$bname.Hp.pch"
+ if { [ is_remote host ] } {
+ remote_download host "$bname.Hp.pch"
+ }
+
+ dg-test -keep-output $test $flags "-I."
+ file delete "$bname.Hp.pch"
+ if { [ file exists "$bname.s" ] } {
+ file rename "$bname.s" "$bname.s-pch"
+ if { [ is_remote host ] } {
+ remote_upload host "[file rootname $test].H" "$bname.Hp"
+ } else {
+ file copy "[file rootname $test].H" "$bname.Hp"
+ }
+ dg-test -keep-output $test $flags "-I."
+ remote_file host delete "$bname.Hp"
+ set tmp [ diff "$bname.s" "$bname.s-pch" ]
+ if { $tmp == 0 } {
+ untested "$nshort $flags assembly comparison"
+ } elseif { $tmp == 1 } {
+ pass "$nshort $flags assembly comparison"
+ } else {
+ fail "$nshort $flags assembly comparison"
+ }
+ file delete "$bname.s"
+ file delete "$bname.s-pch"
+ } else {
+ untested "$nshort $flags assembly comparison"
+ }
+
+ } else {
+ untested $nshort
+ untested "$nshort $flags assembly comparison"
+ }
+ }
+}
+
+set dg-do-what-default "$old_dg_do_what_default"
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/g++.dg/pch/system-1.C b/gcc/testsuite/g++.dg/pch/system-1.C
new file mode 100644
index 00000000000..a0444bc5941
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pch/system-1.C
@@ -0,0 +1,7 @@
+#include "system-1.Hp"
+
+int main()
+{
+ std::cout << "hello world!" << '\n';
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/pch/system-1.H b/gcc/testsuite/g++.dg/pch/system-1.H
new file mode 100644
index 00000000000..604782e4dc7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pch/system-1.H
@@ -0,0 +1 @@
+#include <iostream>
diff --git a/gcc/testsuite/gcc.dg/pch/common-1.c b/gcc/testsuite/gcc.dg/pch/common-1.c
new file mode 100644
index 00000000000..dcf148a2a72
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/common-1.c
@@ -0,0 +1,3 @@
+#include "common-1.hp"
+int foo2 = 3;
+int zz = 2;
diff --git a/gcc/testsuite/gcc.dg/pch/common-1.h b/gcc/testsuite/gcc.dg/pch/common-1.h
new file mode 100644
index 00000000000..971e1996a24
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/common-1.h
@@ -0,0 +1,3 @@
+static int foo1 = 9;
+int foo2;
+extern int zz;
diff --git a/gcc/testsuite/gcc.dg/pch/cpp-1.c b/gcc/testsuite/gcc.dg/pch/cpp-1.c
new file mode 100644
index 00000000000..43256cad545
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/cpp-1.c
@@ -0,0 +1,4 @@
+#include "cpp-1.hp"
+#if !defined(__GNUC__)
+panic! panic!
+#endif
diff --git a/gcc/testsuite/gcc.dg/pch/cpp-1.h b/gcc/testsuite/gcc.dg/pch/cpp-1.h
new file mode 100644
index 00000000000..6e25b021ab5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/cpp-1.h
@@ -0,0 +1 @@
+/* Empty. */
diff --git a/gcc/testsuite/gcc.dg/pch/cpp-2.c b/gcc/testsuite/gcc.dg/pch/cpp-2.c
new file mode 100644
index 00000000000..b76c22cdb04
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/cpp-2.c
@@ -0,0 +1,4 @@
+/* { dg-options "-Wunknown-pragmas -I." } */
+#include "cpp-2.hp"
+#pragma GCC poison not_used
+
diff --git a/gcc/testsuite/gcc.dg/pch/cpp-2.h b/gcc/testsuite/gcc.dg/pch/cpp-2.h
new file mode 100644
index 00000000000..6e25b021ab5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/cpp-2.h
@@ -0,0 +1 @@
+/* Empty. */
diff --git a/gcc/testsuite/gcc.dg/pch/decl-1.c b/gcc/testsuite/gcc.dg/pch/decl-1.c
new file mode 100644
index 00000000000..e4120704d9b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/decl-1.c
@@ -0,0 +1,2 @@
+#include "decl-1.hp"
+int main(void) { return foo; }
diff --git a/gcc/testsuite/gcc.dg/pch/decl-1.h b/gcc/testsuite/gcc.dg/pch/decl-1.h
new file mode 100644
index 00000000000..399f5d3e7f4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/decl-1.h
@@ -0,0 +1 @@
+extern int foo;
diff --git a/gcc/testsuite/gcc.dg/pch/decl-2.c b/gcc/testsuite/gcc.dg/pch/decl-2.c
new file mode 100644
index 00000000000..c374a17e3f7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/decl-2.c
@@ -0,0 +1,2 @@
+#include "decl-2.hp"
+int main(void) { return fun (1, 2); }
diff --git a/gcc/testsuite/gcc.dg/pch/decl-2.h b/gcc/testsuite/gcc.dg/pch/decl-2.h
new file mode 100644
index 00000000000..99c37269097
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/decl-2.h
@@ -0,0 +1,3 @@
+extern int fun (int a, int b);
+
+
diff --git a/gcc/testsuite/gcc.dg/pch/decl-3.c b/gcc/testsuite/gcc.dg/pch/decl-3.c
new file mode 100644
index 00000000000..9c95b9ad08e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/decl-3.c
@@ -0,0 +1,11 @@
+#include "decl-3.hp"
+
+foo_p bar (void)
+{
+ return foop;
+}
+
+struct foo *bar2 (void)
+{
+ return foop;
+}
diff --git a/gcc/testsuite/gcc.dg/pch/decl-3.h b/gcc/testsuite/gcc.dg/pch/decl-3.h
new file mode 100644
index 00000000000..787d480f208
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/decl-3.h
@@ -0,0 +1,3 @@
+struct foo;
+typedef struct foo *foo_p;
+extern foo_p foop;
diff --git a/gcc/testsuite/gcc.dg/pch/decl-4.c b/gcc/testsuite/gcc.dg/pch/decl-4.c
new file mode 100644
index 00000000000..3efe3829ffc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/decl-4.c
@@ -0,0 +1,9 @@
+#include "decl-4.hp"
+
+int bar (foo_p f)
+{
+ if (f->a + foop->a)
+ return f->c->b + foop->b;
+ else
+ return foop->c->b + f->a;
+}
diff --git a/gcc/testsuite/gcc.dg/pch/decl-4.h b/gcc/testsuite/gcc.dg/pch/decl-4.h
new file mode 100644
index 00000000000..3fb220032e0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/decl-4.h
@@ -0,0 +1,7 @@
+typedef struct foo {
+ int a;
+ char b;
+ struct foo *c;
+} foo_s;
+typedef struct foo *foo_p;
+extern foo_p foop;
diff --git a/gcc/testsuite/gcc.dg/pch/decl-5.c b/gcc/testsuite/gcc.dg/pch/decl-5.c
new file mode 100644
index 00000000000..f94b33a1363
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/decl-5.c
@@ -0,0 +1,2 @@
+#include "decl-5.hp"
+static int (*t)(void) = foo;
diff --git a/gcc/testsuite/gcc.dg/pch/decl-5.h b/gcc/testsuite/gcc.dg/pch/decl-5.h
new file mode 100644
index 00000000000..914983c4963
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/decl-5.h
@@ -0,0 +1 @@
+extern int foo(void);
diff --git a/gcc/testsuite/gcc.dg/pch/empty.c b/gcc/testsuite/gcc.dg/pch/empty.c
new file mode 100644
index 00000000000..330876cc7c7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/empty.c
@@ -0,0 +1,8 @@
+/* Yes, it's called "empty" because it has no contents at all.
+ Even this comment goes here, rather than in empty.h. */
+#include "empty.hp"
+
+int main(void)
+{
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pch/empty.h b/gcc/testsuite/gcc.dg/pch/empty.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/empty.h
diff --git a/gcc/testsuite/gcc.dg/pch/except-1.c b/gcc/testsuite/gcc.dg/pch/except-1.c
new file mode 100644
index 00000000000..0332609de2d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/except-1.c
@@ -0,0 +1,7 @@
+/* { dg-options "-fexceptions -I." } */
+#include "except-1.hp"
+
+int main(void)
+{
+ return foo(1);
+}
diff --git a/gcc/testsuite/gcc.dg/pch/except-1.h b/gcc/testsuite/gcc.dg/pch/except-1.h
new file mode 100644
index 00000000000..33a893d1533
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/except-1.h
@@ -0,0 +1,6 @@
+/* { dg-options "-fexceptions" } */
+extern inline int
+foo(int a)
+{
+ return a + 1;
+}
diff --git a/gcc/testsuite/gcc.dg/pch/global-1.c b/gcc/testsuite/gcc.dg/pch/global-1.c
new file mode 100644
index 00000000000..4cab062345e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/global-1.c
@@ -0,0 +1,2 @@
+#include "global-1.hp"
+const int bar = 3;
diff --git a/gcc/testsuite/gcc.dg/pch/global-1.h b/gcc/testsuite/gcc.dg/pch/global-1.h
new file mode 100644
index 00000000000..26efffcb2bb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/global-1.h
@@ -0,0 +1 @@
+const int foo = 2;
diff --git a/gcc/testsuite/gcc.dg/pch/inline-1.c b/gcc/testsuite/gcc.dg/pch/inline-1.c
new file mode 100644
index 00000000000..7fc32d7f766
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/inline-1.c
@@ -0,0 +1,10 @@
+#include "inline-1.hp"
+int bar(int a, int b)
+{
+ return foo(a) + b;
+}
+
+int baz(void)
+{
+ return foo(3);
+}
diff --git a/gcc/testsuite/gcc.dg/pch/inline-1.h b/gcc/testsuite/gcc.dg/pch/inline-1.h
new file mode 100644
index 00000000000..e8f1d6f138f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/inline-1.h
@@ -0,0 +1,5 @@
+extern inline int
+foo(int a)
+{
+ return a * 2 + 1;
+}
diff --git a/gcc/testsuite/gcc.dg/pch/inline-2.c b/gcc/testsuite/gcc.dg/pch/inline-2.c
new file mode 100644
index 00000000000..7792c828b92
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/inline-2.c
@@ -0,0 +1,12 @@
+#include "inline-2.hp"
+extern inline char
+bar(int a)
+{
+ return foo(a)[0];
+}
+
+extern inline char
+baz(void)
+{
+ return foo(0)[0];
+}
diff --git a/gcc/testsuite/gcc.dg/pch/inline-2.h b/gcc/testsuite/gcc.dg/pch/inline-2.h
new file mode 100644
index 00000000000..7d90c63deb9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/inline-2.h
@@ -0,0 +1,5 @@
+extern inline const char *
+foo(int a)
+{
+ return "abcdefgh"+a;
+}
diff --git a/gcc/testsuite/gcc.dg/pch/macro-1.c b/gcc/testsuite/gcc.dg/pch/macro-1.c
new file mode 100644
index 00000000000..3775004a77b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/macro-1.c
@@ -0,0 +1,6 @@
+#include "macro-1.hp"
+
+int main(void)
+{
+ return DEFINED_VALUE + 1 - DEFINED_PARAM (3);
+}
diff --git a/gcc/testsuite/gcc.dg/pch/macro-1.h b/gcc/testsuite/gcc.dg/pch/macro-1.h
new file mode 100644
index 00000000000..5d5b3f4ca65
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/macro-1.h
@@ -0,0 +1,2 @@
+#define DEFINED_VALUE 3
+#define DEFINED_PARAM(x) (x+1)
diff --git a/gcc/testsuite/gcc.dg/pch/macro-2.c b/gcc/testsuite/gcc.dg/pch/macro-2.c
new file mode 100644
index 00000000000..d058e2bb869
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/macro-2.c
@@ -0,0 +1,8 @@
+#define DEFINED_VALUE_2 3
+
+#include "macro-2.hp"
+
+int main(void)
+{
+ return DEFINED_VALUE - DEFINED_VALUE_2;
+}
diff --git a/gcc/testsuite/gcc.dg/pch/macro-2.h b/gcc/testsuite/gcc.dg/pch/macro-2.h
new file mode 100644
index 00000000000..6152a84a877
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/macro-2.h
@@ -0,0 +1,2 @@
+#define DEFINED_VALUE 3
+
diff --git a/gcc/testsuite/gcc.dg/pch/macro-3.c b/gcc/testsuite/gcc.dg/pch/macro-3.c
new file mode 100644
index 00000000000..40ee46e4f3a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/macro-3.c
@@ -0,0 +1,8 @@
+#define DEFINED_FUNC_2(x) (3 + (x))
+
+#include "macro-3.hp"
+
+int main(void)
+{
+ return DEFINED_FUNC (1) - DEFINED_FUNC_2 (-1);
+}
diff --git a/gcc/testsuite/gcc.dg/pch/macro-3.h b/gcc/testsuite/gcc.dg/pch/macro-3.h
new file mode 100644
index 00000000000..d394792a342
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/macro-3.h
@@ -0,0 +1,2 @@
+#define DEFINED_FUNC(x) 3 - (x)
+
diff --git a/gcc/testsuite/gcc.dg/pch/pch.exp b/gcc/testsuite/gcc.dg/pch/pch.exp
new file mode 100644
index 00000000000..69422ca3ef0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/pch.exp
@@ -0,0 +1,100 @@
+# Copyright (C) 1997, 2002 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# GCC testsuite for precompiled header interaction,
+# that uses the `dg.exp' driver.
+
+# Load support procs.
+load_lib gcc-dg.exp
+
+# Initialize `dg'.
+dg-init
+
+set old_dg_do_what_default "${dg-do-what-default}"
+
+# Main loop.
+foreach test [lsort [glob -nocomplain $srcdir/$subdir/*.c]] {
+ global runtests torture_without_loops dg-do-what-default
+
+ # If we're only testing specific files and this isn't one of them, skip it.
+ if ![runtest_file_p $runtests $test] {
+ continue
+ }
+ set nshort [file tail [file dirname $test]]/[file tail $test]
+ set bname "[file rootname [file tail $test]]"
+
+ catch { file delete "$bname.hp.pch" }
+ catch { file delete "$bname.h.pch" }
+ catch { file delete "$bname.s" }
+ catch { file delete "$bname.s-pch" }
+ catch { file delete "$bname.hp" }
+
+ # We don't try to use the loop-optimizing options, since they are highly
+ # unlikely to make any difference to PCH.
+ foreach flags $torture_without_loops {
+ verbose "Testing $nshort, $flags" 1
+
+ # For the header files, the default is to precompile.
+ set dg-do-what-default precompile
+ dg-test -keep-output "[file rootname $test].h" $flags ""
+
+ # For the rest, the default is to compile to .s.
+ set dg-do-what-default compile
+
+ if { [ file exists "$bname.h.pch" ] } {
+ # To ensure that the PCH is used, not the original header,
+ # the actual PCH file is renamed to "<foo>.hp.pch".
+ file rename "$bname.h.pch" "$bname.hp.pch"
+ if { [ is_remote host ] } {
+ remote_download host "$bname.hp.pch"
+ }
+
+ dg-test -keep-output $test $flags "-I."
+ file delete "$bname.hp.pch"
+ if { [ file exists "$bname.s" ] } {
+ file rename "$bname.s" "$bname.s-pch"
+ if { [ is_remote host ] } {
+ remote_upload host "[file rootname $test].h" "$bname.hp"
+ } else {
+ file copy "[file rootname $test].h" "$bname.hp"
+ }
+ dg-test -keep-output $test $flags "-I."
+ remote_file host delete "$bname.hp"
+ set tmp [ diff "$bname.s" "$bname.s-pch" ]
+ if { $tmp == 0 } {
+ untested "$nshort $flags assembly comparison"
+ } elseif { $tmp == 1 } {
+ pass "$nshort $flags assembly comparison"
+ } else {
+ fail "$nshort $flags assembly comparison"
+ }
+ file delete "$bname.s"
+ file delete "$bname.s-pch"
+ } else {
+ untested "$nshort $flags assembly comparison"
+ }
+
+ } else {
+ untested $nshort
+ untested "$nshort $flags assembly comparison"
+ }
+ }
+}
+
+set dg-do-what-default "$old_dg_do_what_default"
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/gcc.dg/pch/static-1.c b/gcc/testsuite/gcc.dg/pch/static-1.c
new file mode 100644
index 00000000000..c1816e949b4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/static-1.c
@@ -0,0 +1,6 @@
+#include "static-1.hp"
+static int bar(void)
+{
+ static int counter;
+ return counter++;
+}
diff --git a/gcc/testsuite/gcc.dg/pch/static-1.h b/gcc/testsuite/gcc.dg/pch/static-1.h
new file mode 100644
index 00000000000..08cc4395d0e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/static-1.h
@@ -0,0 +1,5 @@
+static int foo(void)
+{
+ static int counter;
+ return counter++;
+}
diff --git a/gcc/testsuite/gcc.dg/pch/static-2.c b/gcc/testsuite/gcc.dg/pch/static-2.c
new file mode 100644
index 00000000000..afda874e279
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/static-2.c
@@ -0,0 +1,6 @@
+#include "static-2.hp"
+int bar(void)
+{
+ static int counter;
+ return counter++;
+}
diff --git a/gcc/testsuite/gcc.dg/pch/static-2.h b/gcc/testsuite/gcc.dg/pch/static-2.h
new file mode 100644
index 00000000000..08cc4395d0e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/static-2.h
@@ -0,0 +1,5 @@
+static int foo(void)
+{
+ static int counter;
+ return counter++;
+}
diff --git a/gcc/testsuite/gcc.dg/pch/system-1.c b/gcc/testsuite/gcc.dg/pch/system-1.c
new file mode 100644
index 00000000000..096fe593e06
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/system-1.c
@@ -0,0 +1,6 @@
+#include "system-1.hp"
+int main(void)
+{
+ puts ("hello world!");
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/pch/system-1.h b/gcc/testsuite/gcc.dg/pch/system-1.h
new file mode 100644
index 00000000000..fbfff34edb0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pch/system-1.h
@@ -0,0 +1,2 @@
+#include <stdio.h>
+#include <stdlib.h>
diff --git a/gcc/testsuite/lib/g++-dg.exp b/gcc/testsuite/lib/g++-dg.exp
index 8be839e4dcf..2fad5d1f7f8 100644
--- a/gcc/testsuite/lib/g++-dg.exp
+++ b/gcc/testsuite/lib/g++-dg.exp
@@ -37,6 +37,10 @@ proc g++-dg-test { prog do_what extra_tool_flags } {
set compile_type "object"
set output_file "[file rootname [file tail $prog]].o"
}
+ "precompile" {
+ set compile_type "precompiled_header"
+ set output_file "[file tail $prog].pch"
+ }
"link" {
set compile_type "executable"
set output_file "[file rootname [file tail $prog]].exe"
diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp
index 403fefc2f11..dd130b9c37e 100644
--- a/gcc/testsuite/lib/gcc-dg.exp
+++ b/gcc/testsuite/lib/gcc-dg.exp
@@ -69,6 +69,10 @@ proc gcc-dg-test { prog do_what extra_tool_flags } {
set compile_type "object"
set output_file "[file rootname [file tail $prog]].o"
}
+ "precompile" {
+ set compile_type "precompiled_header"
+ set output_file "[file tail $prog].pch"
+ }
"link" {
set compile_type "executable"
set output_file "[file rootname [file tail $prog]].exe"
diff --git a/gcc/toplev.c b/gcc/toplev.c
index ccc061fc740..f98fc366d4a 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -4666,7 +4666,7 @@ init_asm_output (name)
if (!strcmp (asm_file_name, "-"))
asm_out_file = stdout;
else
- asm_out_file = fopen (asm_file_name, "w");
+ asm_out_file = fopen (asm_file_name, "w+");
if (asm_out_file == 0)
fatal_io_error ("can't open %s for writing", asm_file_name);
}
diff --git a/gcc/tree.c b/gcc/tree.c
index 0247bb957dc..f1549ab89db 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -136,8 +136,8 @@ void
init_ttree ()
{
/* Initialize the hash table of types. */
- type_hash_table = htab_create (TYPE_HASH_INITIAL_SIZE, type_hash_hash,
- type_hash_eq, 0);
+ type_hash_table = htab_create_ggc (TYPE_HASH_INITIAL_SIZE, type_hash_hash,
+ type_hash_eq, 0);
}
diff --git a/gcc/tree.h b/gcc/tree.h
index 6075d83b87f..d8bc1a8c72a 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -98,7 +98,7 @@ enum built_in_function
extern const char *const built_in_names[(int) END_BUILTINS];
/* An array of _DECL trees for the above. */
-extern tree built_in_decls[(int) END_BUILTINS];
+extern GTY(()) tree built_in_decls[(int) END_BUILTINS];
/* The definition of tree nodes fills the next several pages. */
@@ -1273,9 +1273,9 @@ struct tree_type GTY(())
tree pointer_to;
tree reference_to;
union tree_type_symtab {
- int address;
+ int GTY ((tag ("0"))) address;
char * GTY ((tag ("1"))) pointer;
- struct die_struct * GTY ((tag ("2"), skip (""))) die;
+ struct die_struct * GTY ((tag ("2"))) die;
} GTY ((desc ("debug_hooks == &sdb_debug_hooks ? 1 : debug_hooks == &dwarf2_debug_hooks ? 2 : 0"),
descbits ("2"))) symtab;
tree name;
@@ -1881,7 +1881,7 @@ struct tree_decl GTY(())
struct function * GTY ((tag ("FUNCTION_DECL"))) f;
rtx GTY ((tag ("PARM_DECL"))) r;
tree GTY ((tag ("FIELD_DECL"))) t;
- int i;
+ int GTY ((tag ("VAR_DECL"))) i;
} GTY ((desc ("TREE_CODE((tree) &(%0))"))) u2;
/* In a FUNCTION_DECL, this is DECL_SAVED_TREE. */
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 948b1a91e3b..673030d5527 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -107,12 +107,12 @@ struct varasm_status GTY(())
/* Number for making the label on the next
constant that is stored in memory. */
-int const_labelno;
+static GTY(()) int const_labelno;
/* Number for making the label on the next
static variable internal to a function. */
-int var_labelno;
+static GTY(()) int var_labelno;
/* Carry information from ASM_DECLARE_OBJECT_NAME
to ASM_FINISH_DECLARE_OBJECT. */
@@ -179,7 +179,7 @@ static bool asm_emit_uninitialised PARAMS ((tree, const char*, int, int));
static void resolve_unique_section PARAMS ((tree, int, int));
static void mark_weak PARAMS ((tree));
-static enum in_section { no_section, in_text, in_data, in_named
+enum in_section { no_section, in_text, in_data, in_named
#ifdef BSS_SECTION_ASM_OP
, in_bss
#endif
@@ -195,7 +195,8 @@ static enum in_section { no_section, in_text, in_data, in_named
#ifdef EXTRA_SECTIONS
, EXTRA_SECTIONS
#endif
-} in_section = no_section;
+};
+static GTY(()) enum in_section in_section = no_section;
/* Return a nonzero value if DECL has a section attribute. */
#ifndef IN_NAMED_SECTION
@@ -205,18 +206,18 @@ static enum in_section { no_section, in_text, in_data, in_named
#endif
/* Text of section name when in_section == in_named. */
-static const char *in_named_name;
+static GTY(()) const char *in_named_name;
/* Hash table of flags that have been used for a particular named section. */
-struct in_named_entry
+struct in_named_entry GTY(())
{
const char *name;
unsigned int flags;
bool declared;
};
-static htab_t in_named_htab;
+static GTY((param_is (struct in_named_entry))) htab_t in_named_htab;
/* Define functions like text_section for any extra sections. */
#ifdef EXTRA_SECTION_FUNCTIONS
@@ -379,7 +380,7 @@ set_named_section_flags (section, flags)
if (!entry)
{
- entry = (struct in_named_entry *) xmalloc (sizeof (*entry));
+ entry = (struct in_named_entry *) ggc_alloc (sizeof (*entry));
*slot = entry;
entry->name = ggc_strdup (section);
entry->flags = flags;
@@ -2119,7 +2120,7 @@ struct rtx_const GTY(())
ENUM_BITFIELD(kind) kind : 16;
ENUM_BITFIELD(machine_mode) mode : 16;
union rtx_const_un {
- REAL_VALUE_TYPE du;
+ REAL_VALUE_TYPE GTY ((tag ("4"))) du;
struct addr_const GTY ((tag ("1"))) addr;
struct rtx_const_u_di {
HOST_WIDE_INT high;
@@ -4703,8 +4704,8 @@ init_varasm_once ()
{
const_str_htab = htab_create_ggc (128, const_str_htab_hash,
const_str_htab_eq, NULL);
- in_named_htab = htab_create (31, in_named_entry_hash,
- in_named_entry_eq, NULL);
+ in_named_htab = htab_create_ggc (31, in_named_entry_hash,
+ in_named_entry_eq, NULL);
const_alias_set = new_alias_set ();
}
diff --git a/include/ChangeLog b/include/ChangeLog
index f6b05bb7e51..9318821f203 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,11 @@
+2002-07-17 Geoffrey Keating <geoffk@redhat.com>
+
+ * splay-tree.h (GTY): Define if undefined.
+ (splay_tree_allocate_fn): Return PTR for compatibility, not void *.
+ (struct splay_tree_node_s): Support gengtype.
+ (struct splay_tree_s): Likewise. Make allocate_data a PTR,
+ not a void *.
+
2002-11-23 Simon Burge <simonb@wasabisystems.com>
* libiberty.h (basename): Add NetBSD to the list.
diff --git a/include/splay-tree.h b/include/splay-tree.h
index 23f7ac69d42..86707fc1d2f 100644
--- a/include/splay-tree.h
+++ b/include/splay-tree.h
@@ -36,6 +36,10 @@ extern "C" {
#include "ansidecl.h"
+#ifndef GTY
+#define GTY(X)
+#endif
+
/* Use typedefs for the key and data types to facilitate changing
these types, if necessary. These types should be sufficiently wide
that any pointer or scalar can be cast to these types, and then
@@ -65,7 +69,7 @@ typedef int (*splay_tree_foreach_fn) PARAMS((splay_tree_node, void*));
node structures. The first argument is the number of bytes needed;
the second is a data pointer the splay tree functions pass through
to the allocator. This function must never return zero. */
-typedef void *(*splay_tree_allocate_fn) PARAMS((int, void *));
+typedef PTR (*splay_tree_allocate_fn) PARAMS((int, void *));
/* The type of a function used to free memory allocated using the
corresponding splay_tree_allocate_fn. The first argument is the
@@ -74,24 +78,24 @@ typedef void *(*splay_tree_allocate_fn) PARAMS((int, void *));
typedef void (*splay_tree_deallocate_fn) PARAMS((void *, void *));
/* The nodes in the splay tree. */
-struct splay_tree_node_s
+struct splay_tree_node_s GTY(())
{
/* The key. */
- splay_tree_key key;
+ splay_tree_key GTY ((use_param1 (""))) key;
/* The value. */
- splay_tree_value value;
+ splay_tree_value GTY ((use_param2 (""))) value;
/* The left and right children, respectively. */
- splay_tree_node left;
- splay_tree_node right;
+ splay_tree_node GTY ((use_params (""))) left;
+ splay_tree_node GTY ((use_params (""))) right;
};
/* The splay tree itself. */
-typedef struct splay_tree_s
+struct splay_tree_s GTY(())
{
/* The root of the tree. */
- splay_tree_node root;
+ splay_tree_node GTY ((use_params (""))) root;
/* The comparision function. */
splay_tree_compare_fn comp;
@@ -105,9 +109,10 @@ typedef struct splay_tree_s
/* Allocate/free functions, and a data pointer to pass to them. */
splay_tree_allocate_fn allocate;
splay_tree_deallocate_fn deallocate;
- void *allocate_data;
+ PTR GTY((skip (""))) allocate_data;
-} *splay_tree;
+};
+typedef struct splay_tree_s *splay_tree;
extern splay_tree splay_tree_new PARAMS((splay_tree_compare_fn,
splay_tree_delete_key_fn,