+2003-01-09 Geoffrey Keating <geoffk@apple.com>
+
+ Merge from pch-branch:
+
+ 2003-01-06 Geoffrey Keating <geoffk@apple.com>
+
+ * ggc-page.c (ggc_pch_read): Update the statistics after a PCH
+ load.
+
+ 2002-12-24 Geoffrey Keating <geoffk@apple.com>
+
+ * cpplib.c (count_registered_pragmas): New function.
+ (save_registered_pragmas): New function.
+ (_cpp_save_pragma_names): New function.
+ (restore_registered_pragmas): New function.
+ (_cpp_restore_pragma_names): New function.
+ * cpphash.h (_cpp_save_pragma_names): Prototype.
+ (_cpp_restore_pragma_names): Likewise.
+ * cpppch.c (struct save_macro_item): Split from save_macro_data.
+ (struct save_macro_data): New field 'saved_pragmas'.
+ (save_macros): Update for changes to struct save_macro_data.
+ (cpp_prepare_state): Call _cpp_save_pragma_names, update
+ for changes to struct save_macro_data.
+ (cpp_read_state): Call _cpp_restore_pragma_names, update
+ for changes to struct save_macro_data.
+
+ * cpppch.c (cpp_read_state): Restore the hashtable references
+ in the cpp_reader.
+
+ * tree.h (built_in_decls): Mark for PCH.
+
+ * dbxout.c (lastfile): Don't mark for PCH.
+
+ * ggc.h: Document PCH calls into memory managers.
+
+ 2002-12-18 Geoffrey Keating <geoffk@apple.com>
+
+ * doc/invoke.texi (Precompiled Headers): Document the
+ directory form of PCH.
+ * cppfiles.c (validate_pch): New function.
+ (open_file_pch): Search suitably-named directories for PCH files.
+
+ 2002-12-14 Geoffrey Keating <geoffk@apple.com>
+
+ * doc/gty.texi (GTY Options): Document chain_next, chain_prev,
+ reorder options.
+ (Type Information): Mention that the information is also
+ used to implement PCH.
+ * doc/passes.texi (Passes): Improve documentation of
+ language-specific files.
+
+ 2002-12-11 Geoffrey Keating <geoffk@apple.com>
+
+ * gengtype.c (struct write_types_data): Add reorder_note_routine field.
+ (struct walk_type_data): Add reorder_fn field.
+ (walk_type): Process 'reorder' option.
+ (write_types_process_field): Reorder parameters to gt_pch_note_object,
+ call reorder_note_routine.
+ (write_func_for_structure): Reorder parameters to gt_pch_note_object.
+ (ggc_wtd): Update for change to struct write_types_data.
+ (pch_wtd): Likewise.
+ * ggc.h (gt_pch_note_object): Reorder parameters.
+ (gt_handle_reorder): New definition.
+ (gt_pch_note_reorder): New prototype.
+ * ggc-common.c (struct ptr_data): Add reorder_fn.
+ (gt_pch_note_object): Reorder parameters.
+ (gt_pch_note_reorder): New.
+ (gt_pch_save): Call reorder_fn.
+ * stringpool.c (gt_pch_n_S): Update for change to gt_pch_note_object.
+
+ * dbxout.c (cwd): Don't mark for PCH.
+
+ 2002-12-09 Geoffrey Keating <geoffk@apple.com>
+
+ * gengtype.c (finish_root_table): Fix some warnings.
+ (write_root): Handle TYPE_STRING.
+ * ggc.h (gt_ggc_m_S): Add prototype.
+ * stringpool.c (gt_ggc_m_S): New function.
+
+ 2002-11-30 Geoffrey Keating <geoffk@apple.com>
+
+ * dwarf2out.c (dw2_string_counter): New.
+ (AT_string_form): Use it.
+ (same_dw_val_p): Update for removal of hashtable.h hash tables.
+
+ 2002-11-22 Geoffrey Keating <geoffk@apple.com>
+
+ * dbxout.c: Include gt-dbxout.h.
+ (lastfile): Mark for PCH/GGC.
+ (cwd): Likewise.
+ (struct typeinfo): Likewise.
+ (typevec): Likewise.
+ (typevec_len): Likewise.
+ (next_type_number): Likewise.
+ (struct dbx_file): Likewise.
+ (current_file): Likewise.
+ (next_file_number): Likewise.
+ (dbxout_init): Allocate typevec, struct dbx_file with GGC.
+ (dbxout_start_source_file): Allocate struct dbx_file with GGC.
+ (dbxout_end_source_file): Don't free struct dbx_file.
+ (dbxout_type): Use GGC to allocate typevec.
+ * Makefile.in (dbxout.o): Depend on gt-dbxout.h, $(GGC_H).
+ (GTFILES): Add dbxout.c.
+ (gt-dbxout.h): New rule.
+
+ * Makefile.in (c-pch.o): Add debug.h as dependency.
+ * c-pch.c: Include debug.h.
+ (pch_init): Call start_source_file to keep nesting right.
+ (c_common_read_pch): Add orig_name parameter. Call
+ start_source_file debug hook. Call end_source_file debug hook.
+ * c-common.h (c_common_read_pch): Update prototype.
+ * cpplib.h (struct cpp_callbacks): Add fourth field to read_pch
+ callback.
+ * cppfiles.c (struct include_file): Add new field `header_name'.
+ (find_or_create_entry): Default it to `name'.
+ (open_file_pch): Set it to the original header file searched for.
+ (stack_include_file): Don't stack an empty buffer, just handle
+ PCH files immediately. Pass header_name field to read_pch callback.
+
+ 2002-11-19 Geoffrey Keating <geoffk@apple.com>
+
+ * function.c (funcdef_no): Mark to be saved in a PCH.
+
+ 2002-11-15 Geoffrey Keating <geoffk@apple.com>
+
+ * ggc-page.c (ggc_pch_read): Remove unused 'bmap_size'.
+
+ * cpppch.c (cpp_read_state): Correct size reallocated for 'defn'.
+
+ 2002-11-14 Geoffrey Keating <geoffk@apple.com>
+
+ * optabs.h (code_to_optab): Add GTY marker.
+
+ 2002-11-13 Geoffrey Keating <geoffk@apple.com>
+
+ * Makefile.in (GTFILES): Add cpplib.h.
+ * c-common.h (struct c_common_identifier): Don't skip 'node' field.
+ * c-decl.c (build_compound_literal): Don't use var_labelno.
+ * cpplib.h (struct cpp_hashnode): Use gengtype to mark.
+ * dwarf2asm.c (dw2_force_const_mem): Don't use const_labelno.
+ * varasm.c (const_labelno): Use gengtype to mark.
+ (var_labelno): Likewise.
+ (in_section): Likewise.
+ (in_named_name): Likewise.
+ (struct in_named_entry): Likewise.
+ (in_named_htab): Likewise.
+ (set_named_section_flags): Use GGC to allocate struct in_named_entry.
+ (init_varasm_once): Use GGC to allocate in_named_htab.
+ * config/darwin.c (current_pic_label_num): Mark for PCH.
+
+ 2002-11-11 Geoffrey Keating <geoffk@apple.com>
+
+ * ggc-simple.c (init_ggc_pch): New stub procedure.
+ (ggc_pch_count_object): Likewise.
+ (ggc_pch_total_size): Likewise.
+ (ggc_pch_this_base): Likewise.
+ (ggc_pch_alloc_object): Likewise.
+ (ggc_pch_prepare_write): Likewise.
+ (ggc_pch_write_object): Likewise
+ (ggc_pch_finish): Likewise.
+ (ggc_pch_read): Likewise.
+
+ 2002-11-08 Geoffrey Keating <geoffk@apple.com>
+
+ * c-pch.c (c_common_write_pch): Write the macro definitions after
+ the GCed data.
+ (c_common_read_pch): Call cpp_prepare_state. Restore the macro
+ definitions after the GCed data.
+ * cpplib.c (save_macros): New.
+ (reset_ht): New.
+ (cpp_write_pch_deps): Split out of cpp_write_pch.
+ (cpp_write_pch_state): Split out of cpp_write_pch.
+ (cpp_write_pch): Delete.
+ (struct save_macro_data): Delete.
+ (cpp_prepare_state): New.
+ (cpp_read_state): Erase and restore initial macro definitions.
+ * cpplib.h (struct save_macro_data): Forward-declare.
+ (cpp_write_pch_deps): Prototype.
+ (cpp_write_pch_state): Prototype.
+ (cpp_write_pch): Delete prototype.
+ (cpp_prepare_state): Prototype.
+ (cpp_read_state): Add fourth argument.
+
+ 2002-11-04 Geoffrey Keating <geoffk@apple.com>
+
+ * gengtype.c (adjust_field_rtx_def): Don't use skip on valid fields.
+ (write_array): Remove warning.
+
+ * gengtype.c (contains_scalar_p): New.
+ (finish_root_table): Add the table to all languages, even if it's
+ empty.
+ (write_roots): Output gt_pch_scalar_rtab.
+ * ggc-common.c (gt_pch_save): Write out scalars.
+ (gt_pch_restore): Read scalars back.
+
+ * ggc-page.c (OBJECTS_IN_PAGE): New macro.
+ (struct page_entry): Delete pch_page field.
+ (ggc_recalculate_in_use_p): Use OBJECTS_IN_PAGE.
+ (clear_marks): Likewise.
+ (sweep_pages): Likewise.
+ (poison_pages): Likewise.
+ (ggc_print_statistics): Likewise.
+ (ggc_pch_read): Don't free objects read from a PCH.
+ Properly set up in_use_p and page_tails.
+
+ 2002-10-25 Geoffrey Keating <geoffk@apple.com>
+
+ * gengtype.c (struct write_types_data): New.
+ (struct walk_type_data): Make `cookie' const; add extra
+ prev_val item; add `orig_s' field.
+ (walk_type): Update prev_val[3].
+ (write_types_process_field): New.
+ (write_func_for_structure): Take write_types_data structure.
+ (write_types): New.
+ (ggc_wtd): New.
+ (pch_wtd): New.
+ (write_types_local_process_field): New.
+ (gc_mark_process_field): Delete.
+ (write_local_func_for_structure): New.
+ (gc_mark_func_name): Delete.
+ (write_gc_types): Delete.
+ (write_local): New.
+ (finish_root_table): Don't include 'ggc_' in PFX.
+ (write_root): Rename from write_root. Fill pchw field of structures.
+ (write_array): New.
+ (write_roots): Rename from write_gc_roots. Split out to write_array.
+ Update to changes to other routines. Write gt_pch_cache_rtab table.
+ (main): Write PCH walking routines.
+ * ggc-common.c: Include toplev.h, sys/mman.h.
+ (ggc_mark_roots): For cache hashtables, also mark the hash table
+ and the array of entries.
+ (saving_htab): New.
+ (struct ptr_data): New.
+ (POINTER_HASH): New.
+ (gt_pch_note_object): New.
+ (saving_htab_hash): New.
+ (saving_htab_eq): New.
+ (struct traversal_state): New.
+ (call_count): New.
+ (call_alloc): New.
+ (compare_ptr_data): New.
+ (relocate_ptrs): New.
+ (write_pch_globals): New.
+ (struct mmap_info): New.
+ (gt_pch_save): New.
+ (gt_pch_restore): New.
+ * ggc-page.c (ROUND_UP_VALUE): New.
+ (ROUND_UP): New.
+ (struct page_entry): Add field `pch_page'.
+ (init_ggc): Use ROUND_UP.
+ (struct ggc_pch_data): Declare.
+ (init_ggc_pch): New.
+ (ggc_pch_count_object): New.
+ (ggc_pch_total_size): New.
+ (ggc_pch_this_base): New.
+ (ggc_pch_alloc_object): New.
+ (ggc_pch_prepare_write): New.
+ (ggc_pch_write_object): New.
+ (ggc_pch_finish): New.
+ (ggc_pch_read): New.
+ * ggc.h (gt_pointer_operator): New.
+ (gt_note_pointers): New.
+ (gt_pch_note_object): New prototype.
+ (gt_pointer_walker): New.
+ (struct ggc_root_tab): Use gt_pointer_walker, add `pchw' field.
+ (LAST_GGC_ROOT_TAB): Update.
+ (gt_pch_cache_rtab): Declare.
+ (gt_pch_scalar_rtab): Declare.
+ (struct ggc_cache_tab): Use gt_pointer_walker, add `pchw' field.
+ (LAST_GGC_CACHE_TAB): Update.
+ (gt_pch_save_stringpool): Declare.
+ (gt_pch_restore_stringpool): Declare.
+ (gt_pch_p_S): Declare.
+ (gt_pch_n_S): Declare.
+ (struct ggc_pch_data): Forward-declare.
+ (init_ggc_pch): Declare.
+ (ggc_pch_count_object): Declare.
+ (ggc_pch_total_size): Declare.
+ (ggc_pch_this_base): Declare.
+ (ggc_pch_alloc_object): Declare.
+ (ggc_pch_prepare_write): Declare.
+ (ggc_pch_write_object): Declare.
+ (ggc_pch_finish): Declare.
+ (ggc_pch_read): Declare.
+ (gt_pch_save): Declare.
+ (gt_pch_restore): Declare.
+ * fold-const.c (size_int_type_wide): Allocate size_htab using GGC.
+ * emit-rtl.c (init_emit_once): Allocate const_int_htab,
+ const_double_htab, mem_attrs_htab using GGC.
+ * c-pch.c: Include ggc.h.
+ (pch_init): Allow reading PCH file back.
+ (c_common_write_pch): Call gt_pch_save.
+ (c_common_read_pch): Call gt_pch_restore.
+ * c-parse.in (init_reswords): Delete now-untrue comment.
+ Allocate ridpointers using GGC.
+ * c-objc-common.c (c_objc_common_finish_file): Write PCH before
+ calling expand_deferred_fns.
+ * c-common.h (ridpointers): Mark for GTY machinery.
+ * Makefile.in (stringpool.o): Update dependencies.
+ (c-pch.o): Update dependencies.
+ (ggc-common.o): Update dependencies.
+ * stringpool.c: Include gt-stringpool.h.
+ (gt_pch_p_S): New.
+ (gt_pch_n_S): New.
+ (struct string_pool_data): New.
+ (spd): New.
+ (gt_pch_save_stringpool): New.
+ (gt_pch_restore_stringpool): New.
+ * tree.c (init_ttree): Make type_hash_table allocated using GC.
+
+ 2002-10-04 Geoffrey Keating <geoffk@apple.com>
+
+ * gengtype.c (adjust_field_rtx_def): Don't pass size_t to printf.
+ (output_mangled_typename): Don't pass size_t to printf.
+
+ * tree.h (union tree_type_symtab): Add tag to `address' field.
+ (union tree_decl_u2): Add tag to 'i' field.
+ * varasm.c (union rtx_const_un): Add tags to all fields.
+ * gengtype.c (struct walk_type_data): New.
+ (output_escaped_param): Take struct walk_type_data parameter.
+ (write_gc_structure_fields): Delete.
+ (walk_type): New.
+ (write_gc_marker_routine_for_structure): Delete.
+ (write_func_for_structure): New.
+ (gc_mark_process_field): New.
+ (gc_mark_func_name): New.
+ (gc_counter): Delete.
+ (write_gc_types): Use write_func_for_structure.
+ (write_gc_roots): Use walk_type.
+
+ 2002-10-02 Geoffrey Keating <geoffk@apple.com>
+
+ * ggc-common.c (ggc_mark_roots): Delete 'x'.
+ (ggc_splay_dont_free): Fix warning about unused 'x'.
+ (ggc_print_common_statistics): Remove warnings.
+
+ 2002-10-01 Mike Stump <mrs@apple.com>
+
+ * ggc-common.c (ggc_splay_alloc): Actually return the allocated area.
+ * gengtype.c (write_gc_structure_fields): Handle param[digit]_is.
+
+ 2002-09-01 Geoffrey Keating <geoffk@redhat.com>
+ Catherine Moore <clm@redhat.com>
+
+ * Makefile (c-pch.o): Update dependencies.
+ (LIBCPP_OBJS): Add cpppch.o.
+ (cpppch.o): New.
+ * c-common.c (c_common_init): Don't call pch_init here.
+ * c-common.h (c_common_read_pch): Update prototype.
+ * c-lex.c (c_common_parse_file): Call pch_init here.
+ * c-opts.c (COMMAND_LINE_OPTIONS): Add -Winvalid-pch, -fpch-deps.
+ (c_common_decode_option): Handle them.
+ * c-pch.c: Include c-pragma.h.
+ (save_asm_offset): Delete.
+ (pch_init): Move contents of save_asm_offset into here, call
+ cpp_save_state.
+ (c_common_write_pch): Call cpp_write_pch.
+ (c_common_valid_pch): Warn only when -Winvalid-pch. Call
+ cpp_valid_state.
+ (c_common_read_pch): Add NAME parameter. Call cpp_read_state.
+ * cppfiles.c (stack_include_file): Update for change to
+ parameters of cb.read_pch.
+ * cpphash.h (struct cpp_reader): Add `savedstate' field.
+ * cpplib.h (struct cpp_options): Add `warn_invalid_pch' and
+ `restore_pch_deps' fields.
+ (struct cpp_callbacks): Add NAME parameter to `read_pch'.
+ (cpp_save_state): Prototype.
+ (cpp_write_pch): Prototype.
+ (cpp_valid_state): Prototype.
+ (cpp_read_state): Prototype.
+ * cpppch.c: New file.
+ * flags.h (version_flag): Remove prototype.
+ * mkdeps.c (deps_save): New.
+ (deps_restore): New.
+ * mkdeps.h (deps_save): Prototype.
+ (deps_restore): Prototype.
+ * toplev.c (late_init_hook): Delete.
+ (version_flag): Make static again.
+ (compile_file): Don't call late_init_hook.
+ * toplev.h (late_init_hook): Delete.
+ * doc/cppopts.texi: Document -fpch-deps.
+ * doc/invoke.texi (Warning Options): Document -Winvalid-pch.
+
+ 2002-08-27 Geoffrey Keating <geoffk@redhat.com>
+
+ * c-pch.c (c_common_write_pch): Rename from c_write_pch, change
+ callers.
+ (c_common_valid_pch): Rename from c_valid_pch, change callers.
+ (c_common_read_pch): Rename from c_read_pch, change callers.
+
+ * c-opts.c (COMMAND_LINE_OPTIONS): Allow -output-pch= to have
+ a space between it and its argument.
+
+ 2002-08-24 Geoffrey Keating <geoffk@redhat.com>
+
+ * c-pch.c: New file.
+ * toplev.h (late_init_hook): Declare.
+ * toplev.c (late_init_hook): Define.
+ (version_flag): Make globally visible.
+ (compile_file): Call late_init_hook.
+ (init_asm_output): Make output file seekable.
+ * gcc.c (default_compilers): Update c-header rule.
+ * flags.h (version_flag): Declare.
+ * cpplib.h (struct cpp_callbacks): Add 'valid_pch' and 'read_pch'
+ fields.
+ * cppfiles.c (struct include_file): Add 'pch' field.
+ (INCLUDE_PCH_P): New.
+ (open_file_pch): New.
+ (stack_include_file): Handle PCH files specially.
+ (find_include_file): Call open_file_pch instead of open_file.
+ (_cpp_read_file): Explain why open_file is used instead of
+ open_file_pch.
+ * c-opts.c (c_common_decode_option): Correct OPT__output_pch case.
+ * c-objc-common.c (c_objc_common_finish_file): Call c_write_pch.
+ * c-lex.c (init_c_lex): Set valid_pch and read_pch fields
+ in cpplib callbacks.
+ * c-common.c (pch_file): Correct comment.
+ (allow_pch): Define.
+ (c_common_init): Call pch_init.
+ * c-common.h (allow_pch): Declare.
+ (pch_init): Declare.
+ (c_valid_pch): Declare.
+ (c_read_pch): Declare.
+ (c_write_pch): Declare.
+ * Makefile.in (c-pch.o): New.
+ (C_AND_OBJC_OBJS): Add c-pch.o.
+ * doc/invoke.texi (Precompiled Headers): Add index entries,
+ complete truncated paragraph.
+
+ 2002-08-17 Geoffrey Keating <geoffk@redhat.com>
+
+ * c-common.c: (pch_file): Define.
+ * c-common.h (pch_file): Declare.
+ * c-opts.c (COMMAND_LINE_OPTIONS): Add --output-pch=.
+ (missing_arg): Require --output-pch= to have an argument.
+ (c_common_decode_option): Handle --output-pch=.
+ * gcc.c: Document new %V.
+ (default_compilers): Handle compiling C header files.
+ (do_spec_1): Implement %V.
+ (main): Handle "gcc foo.h" without trying to run linker.
+ * doc/invoke.texi (Invoking GCC): Add new menu item for PCH.
+ (Overall Options): Document what the driver does with header files,
+ document new -x option possibilities.
+ (Invoking G++): More documentation for PCH.
+ (Precompiled Headers): New.
+
+ 2002-08-09 Geoffrey Keating <geoffk@redhat.com>
+
+ * ggc.h: Don't include varray.h. Rearrange functions to be more
+ organized.
+ (ggc_add_root): Delete.
+ (ggc_mark_rtx): Delete.
+ (ggc_mark_tree): Delete.
+ (struct ggc_statistics): Remove contents.
+ * ggc-common.c: Remove unneeded includes.
+ (struct ggc_root): Delete.
+ (roots): Delete.
+ (ggc_add_root): Delete.
+ (ggc_mark_roots): Don't mark `roots'. Call ggc_mark_stringpool.
+ (ggc_print_common_statistics): Remove most of the contents.
+ * Makefile.in (GGC_H): No longer uses varray.h.
+ (ggc-common.o): Update dependencies.
+ (c-parse.o): Add varray.h to dependencies.
+ (c-common.o): Add varray.h.
+ * stringpool.c (mark_ident): Use mangled name for tree marker routine.
+ (mark_ident_hash): Rename to ggc_mark_stringpool.
+ (init_stringpool): Don't use ggc_add_root.
+ * c-parse.in: Include varray.h.
+ * c-common.c: Include varray.h.
+ * objc/Make-lang.in (objc-act.o): Add varray.h.
+ * objc/objc-act.c: Include varray.h.
+
+ 2002-07-25 Geoffrey Keating <geoffk@redhat.com>
+
+ * dwarf2out.c (dw_cfi_oprnd2_desc): Fix ISO-only function definition.
+ (dw_cfi_oprnd1_desc): Likewise.
+
+ 2002-07-17 Geoffrey Keating <geoffk@redhat.com>
+
+ * config/alpha/alpha.c (struct alpha_links): Use gengtype to mark;
+ move out of ifdef.
+ (alpha_links): Use gengtype to mark; move out of ifdef.
+ (mark_alpha_links_node): Delete.
+ (mark_alpha_links): Delete.
+ (alpha_need_linkage): Use GGC to allocate splay tree, struct
+ alpha_links, strings. Don't use ggc_add_root.
+ * ggc-common.c (ggc_splay_alloc): New.
+ (ggc_splay_dont_free): New.
+ * ggc.h (ggc_mark_rtx): Update for changed name mangling.
+ (ggc_mark_tree): Likewise.
+ (splay_tree_new_ggc): New.
+ (ggc_splay_alloc): Declare.
+ (ggc_splay_dont_free): Declare.
+ * dwarf2asm.c: Include gt-dwarf2asm.h.
+ (mark_indirect_pool_entry): Delete.
+ (mark_indirect_pool): Delete.
+ (indirect_pool): Use gengtype to mark.
+ (dw2_force_const_mem): Don't use ggc_add_root.
+ * Makefile.in (dwarf2asm.o): Depend on gt-dwarf2asm.h.
+ (GTFILES): Add SPLAY_TREE_H, dwarf2asm.c.
+ (gt-dwarf2asm.h): Depend on s-gtype.
+
+ 2002-07-08 Geoffrey Keating <geoffk@redhat.com>
+
+ * tree.h (union tree_type_symtab): Mark `die' field.
+ * Makefile.in (dwarf2out.o): Update dependencies.
+ * dwarf2out.c: Use GGC to allocate all structures. Convert to htab_t
+ hash tables.
+ (dw_cfi_oprnd1_desc): New function.
+ (dw_cfi_oprnd2_desc): New function.
+ (indirect_string_alloc): Delete.
+ (debug_str_do_hash): New function.
+ (debug_str_eq): New function.
+ (mark_limbo_die_list): Delete.
+ (dwarf2out_init): Don't call ggc_add_root.
+
2003-01-09 Vladimir Makarov <vmakarov@redhat.com>
The following changes are merged from itanium-sched-branch:
the generated code.
(write_automata): Call the new function.
-
Thu Jan 9 22:47:38 CET 2003 Jan Hubicka <jh@suse.cz>
- * i386.md (unit, prefix_0f, memory attributes): Hanlde sseicvt correctly.
+ * i386.md (unit, prefix_0f, memory attributes): Hanlde sseicvt
+ correctly.
2003-01-09 Paolo Carlini <pcarlini@unitus.it>
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)
# 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)
$(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)
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
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 = \
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)
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) \
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) \
$(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@
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
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)
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
+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,
/* 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)")))
@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
#include "c-pragma.h"
#include "rtl.h"
#include "ggc.h"
+#include "varray.h"
#include "expr.h"
#include "c-common.h"
#include "diagnostic.h"
tree c_global_trees[CTI_MAX];
+/* Nonzero if we can read a PCH file now. */
+
+int allow_pch = 1;
+\f
/* Switches common to the C front ends. */
/* Nonzero if prepreprocessing only. */
int flag_preprocess_only;
+/* The file name to which we should write a precompiled header, or
+ NULL if no header will be written in this compile. */
+
+const char *pch_file;
+
/* Nonzero if an ISO standard was selected. It rejects macros in the
user's namespace. */
int flag_iso;
/* 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. */
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]
extern c_language_kind c_language;
+/* Nonzero if we can read a PCH file now. */
+
+extern int allow_pch;
+\f
/* Switches common to the C front ends. */
/* Nonzero if prepreprocessing only. */
+
extern int flag_preprocess_only;
+/* The file name to which we should write a precompiled header, or
+ NULL if no header will be written in this compile. */
+
+extern const char *pch_file;
+
/* Nonzero if an ISO standard was selected. It rejects macros in the
user's namespace. */
+
extern int flag_iso;
/* Nonzero whenever Objective-C functionality is being used. */
/* 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. */
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 */
current_binding_level->parm_order = NULL_TREE;
}
\f
+static GTY(()) int compound_literal_number;
+
/* Build a COMPOUND_LITERAL_EXPR. TYPE is the type given in the compound
literal, which may be an incomplete array type completed by the
initializer; INIT is a CONSTRUCTOR that initializes the compound
/* 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;
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
(*debug_hooks->start_source_file) (lineno, input_filename);
cpp_finish_options (parse_in);
+ pch_init();
+
yyparse ();
free_parser_stacks ();
}
/* 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.
void
c_objc_common_finish_file ()
{
+ if (pch_file)
+ c_common_write_pch ();
+
expand_deferred_fns ();
if (static_ctors)
#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) \
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) \
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) \
switch (cl_options[opt_index].opt_code)
{
+ case OPT__output_pch:
case OPT_Wformat_eq:
case OPT_d:
case OPT_fabi_version:
print_help ();
break;
+ case OPT__output_pch:
+ pch_file = arg;
+ break;
+
case OPT_C:
cpp_opts->discard_comments = 0;
break;
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;
flag_optional_diags = on;
break;
+ case OPT_fpch_deps:
+ cpp_opts->restore_pch_deps = on;
+ break;
+
case OPT_fpermissive:
flag_permissive = on;
break;
#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"
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
--- /dev/null
+/* 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);
+}
#include "target-def.h"
#include "debug.h"
#include "langhooks.h"
+#include <splay-tree.h>
/* Specify which cpu to schedule for. */
#endif /* OBJECT_FORMAT_ELF */
\f
+/* Structure to collect function names for final output
+ in link section. */
+
+enum links_kind {KIND_UNUSED, KIND_LOCAL, KIND_EXTERN};
+
+struct alpha_links GTY(())
+{
+ rtx linkage;
+ enum links_kind kind;
+};
+
+static GTY ((param1_is (char *), param2_is (struct alpha_links *)))
+ splay_tree alpha_links;
+
#if TARGET_ABI_OPEN_VMS
/* Return the VMS argument type corresponding to MODE. */
return GEN_INT (regval);
}
\f
-/* Protect alpha_links from garbage collection. */
-
-static int
-mark_alpha_links_node (node, data)
- splay_tree_node node;
- void *data ATTRIBUTE_UNUSED;
-{
- struct alpha_links *links = (struct alpha_links *) node->value;
- ggc_mark_rtx (links->linkage);
- return 0;
-}
-
-static void
-mark_alpha_links (ptr)
- void *ptr;
-{
- splay_tree tree = *(splay_tree *) ptr;
- splay_tree_foreach (tree, mark_alpha_links_node, NULL);
-}
-
/* Make (or fake) .linkage entry for function call.
IS_LOCAL is 0 if name is used in call, 1 if name is used in definition.
}
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);
static char function_base[32];
-static int current_pic_label_num;
+static GTY(()) int current_pic_label_num;
const char *
machopic_function_base_name ()
};
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));
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));
static rtx generate_set_vrsave PARAMS ((rtx, rs6000_stack_t *, int));
static void altivec_frame_fixup PARAMS ((rtx, rtx, HOST_WIDE_INT));
static int easy_vector_constant PARAMS ((rtx));
+
+/* Hash table stuff for keeping track of TOC entries. */
+
+struct toc_hash_struct GTY(())
+{
+ /* `key' will satisfy CONSTANT_P; in fact, it will satisfy
+ ASM_OUTPUT_SPECIAL_POOL_ENTRY_P. */
+ rtx key;
+ enum machine_mode key_mode;
+ int labelno;
+};
+
+static GTY ((param_is (struct toc_hash_struct))) htab_t toc_hash_table;
\f
/* Default register names. */
char rs6000_reg_names[][8] =
&& (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 ();
*/
-/* 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
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
/* 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;
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
return 4 + rs6000_register_move_cost (mode, class, GENERAL_REGS);
}
+#include "gt-rs6000.h"
# 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
+
+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.
# 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.
# 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 \
# .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
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 \
#include "rtl.h"
#include "toplev.h"
#include "expr.h"
-#include "ggc.h"
#include "diagnostic.h"
extern int inhibit_warnings;
#include "rtl.h"
#include "output.h"
#include "toplev.h"
-#include "ggc.h"
#include "lex.h"
#include "target.h"
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,
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;
{
/* 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);
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)
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.
}
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. */
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;
/* 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)
#ifndef GCC_CP_TREE_H
#define GCC_CP_TREE_H
+#include "ggc.h"
#include "function.h"
#include "hashtab.h"
#include "splay-tree.h"
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;
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. */
} 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;
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;
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;
} 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);
/* 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));
#include "except.h"
#include "toplev.h"
#include "hashtab.h"
-#include "ggc.h"
#include "tm_p.h"
#include "target.h"
#include "c-common.h"
/* 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. */
#include "output.h"
#include "except.h"
#include "toplev.h"
-#include "ggc.h"
#include "timevar.h"
#include "cpplib.h"
#include "target.h"
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;
/* 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. */
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
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)
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;
+ }
}
}
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;
#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;
/* 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";
}
}
/* Add `-lstdc++' if we haven't already done so. */
- if (library)
+ if (library > 0)
{
arglist[j++] = saw_profile_flag ? LIBSTDCXX_PROFILE : LIBSTDCXX;
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++;
#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));
{".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)}\
#include "c-pragma.h"
#include "toplev.h"
#include "output.h"
-#include "ggc.h"
#include "tm_p.h"
#include "timevar.h"
#include "diagnostic.h"
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);
/* 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.
#include "output.h"
#include "flags.h"
#include "toplev.h"
-#include "ggc.h"
#include "tm_p.h"
#include "target.h"
#include "integrate.h"
#include "toplev.h"
#include "varray.h"
-#include "ggc.h"
#include "params.h"
#include "hashtab.h"
#include "debug.h"
#include "decl.h"
#include "flags.h"
#include "diagnostic.h"
-#include "ggc.h"
#include "toplev.h"
#include "output.h"
/* 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
/* 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");
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. */
/* 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;
}
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;
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. */
/* 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. */
/* 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. */
the_parser = cp_parser_new ();
error_occurred = cp_parser_translation_unit (the_parser);
the_parser = NULL;
+
+ finish_file ();
return error_occurred;
}
#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
#include "input.h"
#include "obstack.h"
#include "toplev.h"
-#include "ggc.h"
#include "diagnostic.h"
static tree repo_get_id (tree);
#include "flags.h"
#include "rtl.h"
#include "output.h"
-#include "ggc.h"
#include "toplev.h"
#include "stack.h"
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.
#include "lex.h"
#include "toplev.h"
#include "flags.h"
-#include "ggc.h"
#include "rtl.h"
#include "expr.h"
#include "output.h"
/* Do file scope __FUNCTION__ et al. */
finish_fname_decls ();
-
- finish_file ();
}
/* Finish a template type parameter, specified as AGGR IDENTIFIER.
#include "real.h"
#include "rtl.h"
#include "toplev.h"
-#include "ggc.h"
#include "insn-config.h"
#include "integrate.h"
#include "tree-inline.h"
#include "config.h"
#include "system.h"
+#include <dirent.h>
#include "coretypes.h"
#include "tm.h"
#include "cpplib.h"
/* 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
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
((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 *));
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 *));
{
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,
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
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)
{
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
else
n = name;
- file = open_file (pfile, n);
+ file = open_file_pch (pfile, n);
if (file)
{
file->foundhere = path;
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)
/* 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.
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 *));
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 *));
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
/* 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. */
/* 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. */
/* 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;
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. */
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 *));
--- /dev/null
+/* 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;
+}
#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;
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.
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;
/* 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.
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
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;
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++;
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
}
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;
#endif /* DBX_DEBUGGING_INFO */
#endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */
+
+#include "gt-dbxout.h"
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
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
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
* 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
-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
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
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
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
@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
@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
@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
-@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.
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
VA_CLOSE (ap);
}
\f
-static int mark_indirect_pool_entry PARAMS ((splay_tree_node, void *));
-static void mark_indirect_pool PARAMS ((PTR arg));
static rtx dw2_force_const_mem PARAMS ((rtx));
static int dw2_output_indirect_constant_1 PARAMS ((splay_tree_node, void *));
-static splay_tree indirect_pool;
+static GTY((param1_is (char *), param2_is (tree))) splay_tree indirect_pool;
+
+static GTY(()) int dw2_const_labelno;
#if defined(HAVE_GAS_HIDDEN) && defined(SUPPORTS_ONE_ONLY)
# define USE_LINKONCE_INDIRECT 1
# 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
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 ();
}
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;
VA_CLOSE (ap);
}
+
+#include "gt-dwarf2asm.h"
#include "debug.h"
#include "target.h"
#include "langhooks.h"
-#include "hashtable.h"
#include "hashtab.h"
#ifdef DWARF2_DEBUGGING_INFO
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 ";#"
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;
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;
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;
/* 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;
#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
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 *));
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));
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;
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
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;
{
dwarf2out_reg_save (last_reg_save_label, REGNO (q->reg), q->cfa_offset);
next = q->next;
- free (q);
}
queued_reg_saves = NULL;
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
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. */
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;
if (! USING_SJLJ_EXCEPTIONS && (flag_unwind_tables || flag_exceptions))
output_call_frame_info (1);
}
+#endif
\f
/* And now, the subset of the debugging information support code necessary
for emitting location expressions. */
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,
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;
/* 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;
/* 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;
/* 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 */
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,
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;
#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 *));
dwarf2out_abstract_function, /* outlining_inline_function */
debug_nothing_rtx /* label */
};
+#endif
\f
/* NOTE: In the comments in this file, many references are made to
"Debugging Information Entries". This term is abbreviated as `DIE'
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;
/* 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;
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;
/* The Debugging Information Entry (DIE) structure */
-typedef struct die_struct
+typedef struct die_struct GTY(())
{
enum dwarf_tag die_tag;
char *die_symbol;
/* 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;
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
/* 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;
/* 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;
/* 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. */
/* 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;
#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;
#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;
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));
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));
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 *));
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
}
}
-static inline dw_val_class
+static inline enum dw_val_class
AT_class (a)
dw_attr_ref a;
{
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;
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;
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;
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;
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;
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
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;
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 ();
}
{
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. */
&& (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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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. */
dw_die_ref die;
{
remove_children (die);
- free (die);
}
/* Discard the children of this DIE. */
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;
{
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;
/ 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));
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;
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));
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 ();
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;
{
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++];
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;
{
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);
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);
abort ();
}
}
-
-static void
-mark_limbo_die_list (ptr)
- void *ptr ATTRIBUTE_UNUSED;
-{
- limbo_die_node *node;
- for (node = limbo_die_list; node; node = node->next)
- ggc_mark_tree (node->created_for);
-}
\f
/* Add Ada "use" clause information for SGI Workshop debugger. */
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. */
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. */
{
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. */
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;
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 */
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);
}
}
-/* 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;
else
abort ();
}
-
- free (node);
}
limbo_die_list = NULL;
/* 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
/* 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;
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);
}
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. */
%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.
%(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},
this_is_library_file = 1;
break;
+ case 'V':
+ outfiles[input_file_number] = NULL;
+ break;
+
case 'w':
this_is_output_file = 1;
break;
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;
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;
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;
}
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. */
}
}
-/* 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--)
&& 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)
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)
&& 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");
|| 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");
/* 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)
{
{
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)
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");
{
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);
}
}
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. */
const char *name;
{
struct flist *fli2;
- unsigned started_bitmap = 0;
for (fli2 = flp; fli2; fli2 = fli2->next)
if (fli2->started_p)
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)
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");
+ }
}
}
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;
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);
}
}
{
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);
}
}
{
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;
if (! has_length && UNION_OR_STRUCT_P (tp))
{
- oprintf (f, " >_ggc_mx_%s\n", tp->u.s.tag);
+ oprintf (f, " >_ggc_mx_%s,\n", tp->u.s.tag);
+ oprintf (f, " >_pch_nx_%s", tp->u.s.tag);
}
else if (! has_length && tp->kind == TYPE_PARAM_STRUCT)
{
oprintf (f, " >_ggc_m_");
output_mangled_typename (f, tp);
+ oprintf (f, ",\n >_pch_n_");
+ output_mangled_typename (f, tp);
}
else if (has_length
&& (tp->kind == TYPE_POINTER || UNION_OR_STRUCT_P (tp)))
{
- oprintf (f, " >_ggc_ma_%s", name);
+ oprintf (f, " >_ggc_ma_%s,\n", name);
+ oprintf (f, " >_pch_na_%s", name);
}
else
{
}
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, " >_ggc_m_S,\n");
+ oprintf (f, " >_pch_n_S\n");
+ oprintf (f, " },\n");
+ }
+ break;
+
+ case TYPE_SCALAR:
break;
default:
}
}
+/* 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;
&& (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);
}
}
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)
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)
oprintf (f, "[] = {\n");
}
- write_gc_root (f, v, v->type->u.p->u.param_struct.param[0],
+ write_root (f, v, v->type->u.p->u.param_struct.param[0],
v->name, length_p, &v->line, if_marked);
}
- finish_root_table (flp, "rc", "LAST_GGC_CACHE_TAB", "ggc_cache_tab",
+ finish_root_table (flp, "ggc_rc", "LAST_GGC_CACHE_TAB", "ggc_cache_tab",
"gt_ggc_cache_rtab");
+
+ for (v = variables; v; v = v->next)
+ {
+ outf_p f = get_output_file_with_visibility (v->line.file);
+ struct flist *fli;
+ int length_p = 0;
+ int if_marked_p = 0;
+ options_p o;
+
+ for (o = v->opt; o; o = o->next)
+ if (strcmp (o->name, "length") == 0)
+ length_p = 1;
+ else if (strcmp (o->name, "if_marked") == 0)
+ if_marked_p = 1;
+
+ if (! if_marked_p)
+ continue;
+
+ for (fli = flp; fli; fli = fli->next)
+ if (fli->f == f)
+ break;
+ if (! fli->started_p)
+ {
+ fli->started_p = 1;
+
+ oprintf (f, "const struct ggc_root_tab gt_pch_rc_");
+ put_mangled_filename (f, v->line.file);
+ oprintf (f, "[] = {\n");
+ }
+
+ write_root (f, v, v->type, v->name, length_p, &v->line, NULL);
+ }
+
+ finish_root_table (flp, "pch_rc", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
+ "gt_pch_cache_rtab");
+
+ for (v = variables; v; v = v->next)
+ {
+ outf_p f = get_output_file_with_visibility (v->line.file);
+ struct flist *fli;
+ int skip_p = 0;
+ options_p o;
+
+ for (o = v->opt; o; o = o->next)
+ if (strcmp (o->name, "deletable") == 0
+ || strcmp (o->name, "if_marked") == 0)
+ skip_p = 1;
+
+ if (skip_p)
+ continue;
+
+ if (! contains_scalar_p (v->type))
+ continue;
+
+ for (fli = flp; fli; fli = fli->next)
+ if (fli->f == f)
+ break;
+ if (! fli->started_p)
+ {
+ fli->started_p = 1;
+
+ oprintf (f, "const struct ggc_root_tab gt_pch_rs_");
+ put_mangled_filename (f, v->line.file);
+ oprintf (f, "[] = {\n");
+ }
+
+ oprintf (f, " { &%s, 1, sizeof (%s), NULL, NULL },\n",
+ v->name, v->name);
+ }
+
+ finish_root_table (flp, "pch_rs", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
+ "gt_pch_scalar_rtab");
}
\f
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 ();
#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
/* Statistics about the allocation. */
static ggc_statistics *ggc_stats;
+struct traversal_state;
+
static int ggc_htab_delete PARAMS ((void **, void *));
+static hashval_t saving_htab_hash PARAMS ((const PTR));
+static int saving_htab_eq PARAMS ((const PTR, const PTR));
+static int call_count PARAMS ((void **, void *));
+static int call_alloc PARAMS ((void **, void *));
+static int compare_ptr_data PARAMS ((const void *, const void *));
+static void relocate_ptrs PARAMS ((void *, void *));
+static void write_pch_globals PARAMS ((const struct ggc_root_tab * const *tab,
+ struct traversal_state *state));
/* Maintain global roots th