+void
+gt_pch_save (FILE *f)
+{
+ const struct ggc_root_tab *const *rt;
+ const struct ggc_root_tab *rti;
+ size_t i;
+ struct traversal_state state;
+ char *this_object = NULL;
+ size_t this_object_size = 0;
+ struct mmap_info mmi;
+ const size_t mmap_offset_alignment = host_hooks.gt_pch_alloc_granularity();
+
+ gt_pch_save_stringpool ();
+
+ saving_htab = htab_create (50000, saving_htab_hash, saving_htab_eq, free);
+
+ for (rt = gt_ggc_rtab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ for (i = 0; i < rti->nelt; i++)
+ (*rti->pchw)(*(void **)((char *)rti->base + rti->stride * i));
+
+ for (rt = gt_pch_cache_rtab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ for (i = 0; i < rti->nelt; i++)
+ (*rti->pchw)(*(void **)((char *)rti->base + rti->stride * i));
+
+ /* Prepare the objects for writing, determine addresses and such. */
+ state.f = f;
+ state.d = init_ggc_pch();
+ state.count = 0;
+ htab_traverse (saving_htab, call_count, &state);
+
+ mmi.size = ggc_pch_total_size (state.d);
+
+ /* Try to arrange things so that no relocation is necessary, but
+ don't try very hard. On most platforms, this will always work,
+ and on the rest it's a lot of work to do better.
+ (The extra work goes in HOST_HOOKS_GT_PCH_GET_ADDRESS and
+ HOST_HOOKS_GT_PCH_USE_ADDRESS.) */
+ mmi.preferred_base = host_hooks.gt_pch_get_address (mmi.size, fileno (f));
+
+ ggc_pch_this_base (state.d, mmi.preferred_base);
+
+ state.ptrs = XNEWVEC (struct ptr_data *, state.count);
+ state.ptrs_i = 0;
+ htab_traverse (saving_htab, call_alloc, &state);
+ qsort (state.ptrs, state.count, sizeof (*state.ptrs), compare_ptr_data);
+
+ /* Write out all the scalar variables. */
+ for (rt = gt_pch_scalar_rtab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ if (fwrite (rti->base, rti->stride, 1, f) != 1)
+ fatal_error ("can't write PCH file: %m");
+
+ /* Write out all the global pointers, after translation. */
+ write_pch_globals (gt_ggc_rtab, &state);
+ write_pch_globals (gt_pch_cache_rtab, &state);
+
+ /* Pad the PCH file so that the mmapped area starts on an allocation
+ granularity (usually page) boundary. */
+ {
+ long o;
+ o = ftell (state.f) + sizeof (mmi);
+ if (o == -1)
+ fatal_error ("can't get position in PCH file: %m");
+ mmi.offset = mmap_offset_alignment - o % mmap_offset_alignment;
+ if (mmi.offset == mmap_offset_alignment)
+ mmi.offset = 0;
+ mmi.offset += o;
+ }
+ if (fwrite (&mmi, sizeof (mmi), 1, state.f) != 1)
+ fatal_error ("can't write PCH file: %m");
+ if (mmi.offset != 0
+ && fseek (state.f, mmi.offset, SEEK_SET) != 0)
+ fatal_error ("can't write padding to PCH file: %m");
+
+ ggc_pch_prepare_write (state.d, state.f);
+
+ /* Actually write out the objects. */
+ for (i = 0; i < state.count; i++)