This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[pph] Merge and rename pph sources. (issue5440063)
- From: crowl at google dot com (Lawrence Crowl)
- To: reply at codereview dot appspotmail dot com, dnovillo at google dot com, gcc-patches at gcc dot gnu dot org
- Date: Tue, 29 Nov 2011 21:09:39 -0800 (PST)
- Subject: [pph] Merge and rename pph sources. (issue5440063)
Merge pph.c and pph-streamer.c into pph-core.c.
Shorten pph-streamer-in.c to pph-in.c.
Shorten pph-streamer-out.c to pph-out.c.
Reduce redundancies in make dependences.
Index: gcc/cp/ChangeLog.pph
2011-11-29 Lawrence Crowl <crowl@google.com>
* pph-streamer.c: Renamed pph-core.c.
* pph.c: Contents moved into pph-core.c.
(pph_dump_min_decl): Removed unused.
(flatten_name): Rename pph_flatten_name.
* pph-streamer-in.c: Renamed pph-in.c.
* pph-streamer-out.c: Renamed pph-out.c.
* pph-streamer.h: Adjust to reflect above. Remove unneeded decls.
* pph.h: Adjust to reflect above.
* config-lang.in: Adjust to reflect above.
* Make-lang.in: Adjust to reflect above.
(CXX_PPH_STREAMER_H): Remove redundancies.
(CXX_PPH_COMMON_H): New.
(CXX_PPH_COMMON_H): New.
(cp/pph-core.o): Remove redundancies.
(cp/pph-in.o): Remove redundancies.
(cp/pph-out.o): Remove redundancies.
(cp/pt.o): Add depndence on CXX_PPH_H.
* pt.c: Remove redundant #include "pph-streamer.h".
Index: gcc/cp/pph-core.c
===================================================================
--- gcc/cp/pph-core.c (revision 181815)
+++ gcc/cp/pph-core.c (working copy)
@@ -1,6 +1,8 @@
-/* Routines for streaming PPH data.
- Copyright (C) 2011 Free Software Foundation, Inc.
- Contributed by Diego Novillo <dnovillo@google.com>.
+/* Factored pre-parsed header (PPH) support for C++.
+ Common routines for streaming PPH data.
+ Copyright (C) 2010, 2011 Free Software Foundation, Inc.
+ Contributed by Lawrence Crowl <crowl@google.com> and
+ Diego Novillo <dnovillo@google.com>.
This file is part of GCC.
@@ -18,320 +20,131 @@ You should have received a copy of the G
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
+
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "pph.h"
+#include "cpplib.h"
+#include "toplev.h"
#include "tree.h"
+#include "cp-tree.h"
#include "langhooks.h"
+#include "timevar.h"
#include "tree-iterator.h"
#include "tree-pretty-print.h"
#include "lto-streamer.h"
#include "pph-streamer.h"
+#include "pointer-set.h"
+#include "fixed-value.h"
+#include "md5.h"
#include "tree-pass.h"
+#include "tree-dump.h"
+#include "tree-inline.h"
+#include "tree-pretty-print.h"
+#include "cxx-pretty-print.h"
+#include "parser.h"
#include "version.h"
#include "cppbuiltin.h"
#include "streamer-hooks.h"
-/* List of PPH images opened for reading. Images opened during #include
- processing and opened from pph_in_includes cannot be closed
- immediately after reading, because the pickle cache contained in
- them may be referenced from other images. We delay closing all of
- them until the end of parsing (when pph_streamer_finish is called). */
-static VEC(pph_stream_ptr, heap) *pph_read_images = NULL;
-
-/* A cache of pre-loaded common tree nodes. */
-static pph_cache *pph_preloaded_cache;
-
-/* Pre-load common tree nodes into CACHE. These nodes are always built by the
- front end, so there is no need to pickle them. */
-
-static void
-pph_cache_preload (pph_cache *cache)
-{
- unsigned i;
-
- for (i = itk_char; i < itk_none; i++)
- pph_cache_add (cache, integer_types[i], NULL,
- pph_tree_code_to_tag (integer_types[i]));
-
- for (i = 0; i < TYPE_KIND_LAST; i++)
- pph_cache_add (cache, sizetype_tab[i], NULL,
- pph_tree_code_to_tag (sizetype_tab[i]));
-
- /* global_trees[] can have NULL entries in it. Skip them. */
- for (i = 0; i < TI_MAX; i++)
- if (global_trees[i])
- pph_cache_add (cache, global_trees[i], NULL,
- pph_tree_code_to_tag (global_trees[i]));
-
- /* c_global_trees[] can have NULL entries in it. Skip them. */
- for (i = 0; i < CTI_MAX; i++)
- if (c_global_trees[i])
- pph_cache_add (cache, c_global_trees[i], NULL,
- pph_tree_code_to_tag (c_global_trees[i]));
-
- /* cp_global_trees[] can have NULL entries in it. Skip them. */
- for (i = 0; i < CPTI_MAX; i++)
- {
- /* Also skip trees which are generated while parsing. */
- if (i == CPTI_KEYED_CLASSES)
- continue;
-
- if (cp_global_trees[i])
- pph_cache_add (cache, cp_global_trees[i], NULL,
- pph_tree_code_to_tag (cp_global_trees[i]));
- }
-
- /* Add other well-known nodes that should always be taken from the
- current compilation context. */
- pph_cache_add (cache, global_namespace, NULL,
- pph_tree_code_to_tag (global_namespace));
- pph_cache_add (cache, DECL_CONTEXT (global_namespace), NULL,
- pph_tree_code_to_tag (DECL_CONTEXT (global_namespace)));
-}
-
-
-/* Callback for writing ASTs to a stream. Write EXPR to the PPH stream
- in OB. */
-
-static void
-pph_write_tree (struct output_block *ob, tree expr, bool ref_p ATTRIBUTE_UNUSED)
-{
- pph_out_tree ((pph_stream *) ob->sdata, expr);
-}
-
-
-/* Callback for reading ASTs from a stream. Instantiate and return a
- new tree from the PPH stream in DATA_IN. */
-static tree
-pph_read_tree (struct lto_input_block *ib ATTRIBUTE_UNUSED,
- struct data_in *data_in)
-{
- return pph_in_tree ((pph_stream *) data_in->sdata);
-}
-
-
-/* Callback for streamer_hooks.input_location. An offset is applied to
- the location_t read in according to the properties of the merged
- line_table. IB and DATA_IN are as in lto_input_location. This function
- should only be called after pph_in_and_merge_line_table was called as
- we expect pph_loc_offset to be set. */
-
-static location_t
-pph_input_location (struct lto_input_block *ib ATTRIBUTE_UNUSED,
- struct data_in *data_in)
-{
- return pph_in_location ((pph_stream *) data_in->sdata);
-}
-
-
-/* Callback for streamer_hooks.output_location. Output the LOC directly,
- an offset will be applied on input after rebuilding the line_table.
- OB and LOC are as in lto_output_location. */
-
-static void
-pph_output_location (struct output_block *ob, location_t loc)
-{
- pph_out_location ((pph_stream *) ob->sdata, loc);
-}
-
-
-/* Initialize all the streamer hooks used for streaming ASTs. */
-
-static void
-pph_hooks_init (void)
-{
- streamer_hooks_init ();
- streamer_hooks.write_tree = pph_write_tree;
- streamer_hooks.read_tree = pph_read_tree;
- streamer_hooks.input_location = pph_input_location;
- streamer_hooks.output_location = pph_output_location;
-}
+/*************************************************************** pph logging */
-/* Initialize an empty pickle CACHE. */
-
-static void
-pph_cache_init (pph_cache *cache)
-{
- cache->v = NULL;
- cache->m = pointer_map_create ();
-}
+/* Log file where PPH analysis is written to. Controlled by
+ -fpph_logfile. If this flag is not given, stdout is used. */
+FILE *pph_logfile = NULL;
-/* Initialize the pre-loaded cache. This contains all the common
- tree nodes built by the compiler on startup. */
+/* Convert a checked tree_code CODE to a string. */
-static void
-pph_init_preloaded_cache (void)
+const char *
+pph_tree_code_text (enum tree_code code)
{
- pph_preloaded_cache = XCNEW (pph_cache);
- pph_cache_init (pph_preloaded_cache);
- pph_cache_preload (pph_preloaded_cache);
+ gcc_assert (code < MAX_TREE_CODES);
+ return tree_code_name[code];
}
-/* Initialize the streamer. */
+/* Dump a location LOC to FILE. */
void
-pph_streamer_init (void)
+pph_dump_location (FILE *file, location_t loc)
{
- pph_hooks_init ();
- pph_init_preloaded_cache ();
+ expanded_location xloc = expand_location (loc);
+ fprintf (file, "%s:%d", xloc.file, xloc.line);
}
-/* Finalize the streamer. */
+/* Dump a complicated name for tree T to FILE using FLAGS.
+ See TDF_* in tree-pass.h for flags. */
void
-pph_streamer_finish (void)
+pph_dump_tree_name (FILE *file, tree t, int flags)
{
- unsigned i;
- pph_stream *image;
-
- /* Finalize the writer. */
- pph_writer_finish ();
-
- /* Finalize the reader. */
- pph_reader_finish ();
-
- /* Close any images read during parsing. */
- FOR_EACH_VEC_ELT (pph_stream_ptr, pph_read_images, i, image)
- pph_stream_close (image);
-
- VEC_free (pph_stream_ptr, heap, pph_read_images);
+ enum tree_code code = TREE_CODE (t);
+ const char *text = pph_tree_code_text (code);
+ if (DECL_P (t))
+ fprintf (file, "%s %s\n", text, decl_as_string (t, flags));
+ else if (TYPE_P (t))
+ fprintf (file, "%s %s\n", text, type_as_string (t, flags));
+ else if (EXPR_P (t))
+ fprintf (file, "%s %s\n", text, expr_as_string (t, flags));
+ else
+ {
+ fprintf (file, "%s ", text );
+ print_generic_expr (file, t, flags);
+ fprintf (file, "\n");
+ }
}
-/* If FILENAME has already been read, return the stream associated with it. */
-
-static pph_stream *
-pph_find_stream_for (const char *filename)
-{
- pph_stream *include;
- unsigned i;
-
- /* FIXME pph, implement a hash map to avoid this linear search. */
- FOR_EACH_VEC_ELT (pph_stream_ptr, pph_read_images, i, include)
- if (strcmp (include->name, filename) == 0)
- return include;
-
- return NULL;
-}
+static void
+pph_dump_binding (FILE *file, cp_binding_level *level);
-/* Add STREAM to the list of read images. */
+/* Dump namespace NS for PPH. */
void
-pph_mark_stream_read (pph_stream *stream)
+pph_dump_namespace (FILE *file, tree ns)
{
- stream->in_memory_p = true;
- VEC_safe_push (pph_stream_ptr, heap, pph_read_images, stream);
+ fprintf (file, "namespace ");
+ pph_dump_tree_name (file, ns, 0);
+ fprintf (file, "{\n");
+ pph_dump_binding (file, NAMESPACE_LEVEL (ns));
+ fprintf (file, "}\n");
}
-/* Create a new PPH stream to be stored on the file called NAME.
- MODE is passed to fopen directly. */
+/* Dump a CHAIN for PPH. */
-pph_stream *
-pph_stream_open (const char *name, const char *mode)
+static void
+pph_dump_chain (FILE *file, tree chain)
{
- pph_stream *stream;
- FILE *f;
-
- /* If we have already opened a PPH stream named NAME, just return
- its associated stream. */
- stream = pph_find_stream_for (name);
- if (stream)
+ tree t, next;
+ for (t = chain; t; t = next)
{
- gcc_assert (stream->in_memory_p);
- return stream;
+ next = DECL_CHAIN (t);
+ if (!DECL_IS_BUILTIN (t))
+ pph_dump_tree_name (file, t, 0);
}
-
- f = fopen (name, mode);
- if (!f)
- return NULL;
-
- stream = XCNEW (pph_stream);
- stream->file = f;
- stream->name = xstrdup (name);
- stream->write_p = (strchr (mode, 'w') != NULL);
- pph_cache_init (&stream->cache);
- stream->preloaded_cache = pph_preloaded_cache;
- if (stream->write_p)
- pph_init_write (stream);
- else
- pph_init_read (stream);
-
- return stream;
}
-
-/* Close PPH stream STREAM. */
+/* Dump cp_binding_level LEVEL for PPH. */
void
-pph_stream_close (pph_stream *stream)
+pph_dump_binding (FILE *file, cp_binding_level *level)
{
- /* STREAM can be NULL if it could not be properly opened. An error
- has already been emitted, so avoid crashing here. */
- if (stream == NULL)
- return;
-
- if (flag_pph_tracer >= 1)
- fprintf (pph_logfile, "PPH: Closing %s\n", stream->name);
-
- /* If we were writing to STREAM, flush all the memory buffers. This
- does the actual writing of all the pickled data structures. */
- if (stream->write_p)
- pph_flush_buffers (stream);
-
- fclose (stream->file);
-
- /* Deallocate all memory used. */
- stream->file = NULL;
- VEC_free (pph_cache_entry, heap, stream->cache.v);
- pointer_map_destroy (stream->cache.m);
- VEC_free (pph_symtab_entry, heap, stream->symtab.v);
- VEC_free (pph_stream_ptr, heap, stream->includes);
-
- if (stream->write_p)
- {
- destroy_output_block (stream->encoder.w.ob);
- free (stream->encoder.w.decl_state_stream);
- lto_delete_out_decl_state (stream->encoder.w.out_state);
- }
- else
+ tree t, next;
+ pph_dump_chain (file, level->names);
+ for (t = level->namespaces; t; t = next)
{
- unsigned i;
-
- free (stream->encoder.r.ib);
- lto_data_in_delete (stream->encoder.r.data_in);
- for (i = 0; i < PPH_NUM_SECTIONS; i++)
- free (stream->encoder.r.pph_sections[i]);
- free (stream->encoder.r.pph_sections);
- free (stream->encoder.r.file_data);
+ next = DECL_CHAIN (t);
+ if (!DECL_IS_BUILTIN (t))
+ pph_dump_namespace (file, t);
}
-
- free (stream);
-}
-
-
-/* Add INCLUDE, and the images included by it, to the list of files
- included by STREAM. */
-
-void
-pph_add_include (pph_stream *stream, pph_stream *include)
-{
- pph_stream *include_child;
- unsigned i;
-
- include->parent = stream;
- VEC_safe_push (pph_stream_ptr, heap, stream->includes, include);
- FOR_EACH_VEC_ELT (pph_stream_ptr, include->includes, i, include_child)
- VEC_safe_push (pph_stream_ptr, heap, stream->includes, include_child);
}
@@ -367,6 +180,10 @@ static const char *tag_strings[] =
"PPH_sorted_fields_type"
};
+
+/* Trace print a MARKER and TAG. */
+
+
void
pph_trace_marker (enum pph_record_marker marker, enum pph_tag tag)
{
@@ -456,6 +273,84 @@ pph_trace_tree (tree t, enum pph_trace_e
}
+/************************************************* pph pointer mapping cache */
+
+
+/* Initialize an empty pickle CACHE. */
+
+static void
+pph_cache_init (pph_cache *cache)
+{
+ cache->v = NULL;
+ cache->m = pointer_map_create ();
+}
+
+
+/* A cache of pre-loaded common tree nodes. */
+static pph_cache *pph_preloaded_cache;
+
+
+/* Pre-load common tree nodes into CACHE. These nodes are always built by the
+ front end, so there is no need to pickle them. */
+
+static void
+pph_cache_preload (pph_cache *cache)
+{
+ unsigned i;
+
+ for (i = itk_char; i < itk_none; i++)
+ pph_cache_add (cache, integer_types[i], NULL,
+ pph_tree_code_to_tag (integer_types[i]));
+
+ for (i = 0; i < TYPE_KIND_LAST; i++)
+ pph_cache_add (cache, sizetype_tab[i], NULL,
+ pph_tree_code_to_tag (sizetype_tab[i]));
+
+ /* global_trees[] can have NULL entries in it. Skip them. */
+ for (i = 0; i < TI_MAX; i++)
+ if (global_trees[i])
+ pph_cache_add (cache, global_trees[i], NULL,
+ pph_tree_code_to_tag (global_trees[i]));
+
+ /* c_global_trees[] can have NULL entries in it. Skip them. */
+ for (i = 0; i < CTI_MAX; i++)
+ if (c_global_trees[i])
+ pph_cache_add (cache, c_global_trees[i], NULL,
+ pph_tree_code_to_tag (c_global_trees[i]));
+
+ /* cp_global_trees[] can have NULL entries in it. Skip them. */
+ for (i = 0; i < CPTI_MAX; i++)
+ {
+ /* Also skip trees which are generated while parsing. */
+ if (i == CPTI_KEYED_CLASSES)
+ continue;
+
+ if (cp_global_trees[i])
+ pph_cache_add (cache, cp_global_trees[i], NULL,
+ pph_tree_code_to_tag (cp_global_trees[i]));
+ }
+
+ /* Add other well-known nodes that should always be taken from the
+ current compilation context. */
+ pph_cache_add (cache, global_namespace, NULL,
+ pph_tree_code_to_tag (global_namespace));
+ pph_cache_add (cache, DECL_CONTEXT (global_namespace), NULL,
+ pph_tree_code_to_tag (DECL_CONTEXT (global_namespace)));
+}
+
+
+/* Initialize the pre-loaded cache. This contains all the common
+ tree nodes built by the compiler on startup. */
+
+static void
+pph_init_preloaded_cache (void)
+{
+ pph_preloaded_cache = XCNEW (pph_cache);
+ pph_cache_init (pph_preloaded_cache);
+ pph_cache_preload (pph_preloaded_cache);
+}
+
+
/* Insert DATA in CACHE at slot IX. TAG represents the data structure
pointed-to by DATA. As a restriction to prevent stomping on cache
entries, this will not allow inserting into the same slot more than
@@ -485,6 +380,30 @@ pph_cache_insert_at (pph_cache *cache, v
}
+/* Add pointer DATA with data type TAG to CACHE. If IX_P is not NULL,
+ on exit *IX_P will contain the slot number where DATA is stored.
+ Return the newly added entry. */
+
+pph_cache_entry *
+pph_cache_add (pph_cache *cache, void *data, unsigned *ix_p, enum pph_tag tag)
+{
+ unsigned ix;
+ pph_cache_entry *e;
+
+ e = pph_cache_lookup (cache, data, &ix, tag);
+ if (e == NULL)
+ {
+ ix = VEC_length (pph_cache_entry, cache->v);
+ e = pph_cache_insert_at (cache, data, ix, tag);
+ }
+
+ if (ix_p)
+ *ix_p = ix;
+
+ return e;
+}
+
+
/* If DATA exists in CACHE, return the cache entry holding it. If
IX_P is not NULL, store the cache slot where DATA resides in *IX_P
(or (unsigned)-1 if DATA is not found). If CACHE is NULL use
@@ -591,28 +510,7 @@ pph_cache_lookup_in_includes (pph_stream
}
-/* Add pointer DATA with data type TAG to CACHE. If IX_P is not NULL,
- on exit *IX_P will contain the slot number where DATA is stored.
- Return the newly added entry. */
-
-pph_cache_entry *
-pph_cache_add (pph_cache *cache, void *data, unsigned *ix_p, enum pph_tag tag)
-{
- unsigned ix;
- pph_cache_entry *e;
-
- e = pph_cache_lookup (cache, data, &ix, tag);
- if (e == NULL)
- {
- ix = VEC_length (pph_cache_entry, cache->v);
- e = pph_cache_insert_at (cache, data, ix, tag);
- }
-
- if (ix_p)
- *ix_p = ix;
-
- return e;
-}
+/*************************************************** tree contents signature */
/* Associate signature CRC with the first NBYTES of the area memory
@@ -672,3 +570,511 @@ pph_get_signature (tree t, size_t *nbyte
return crc;
}
+
+
+/****************************************************** pph include handling */
+
+
+/* Return true if PPH image NAME can be used at the point of inclusion
+ (given by LOC). */
+
+static bool
+pph_is_valid_here (const char *name, location_t loc)
+{
+ /* If we are inside a scope, reject the image. We could be inside a
+ namespace or a structure which changes the parsing context for
+ the original text file. */
+ if (scope_chain->x_brace_nesting > 0)
+ {
+ error_at (loc, "PPH file %s not included at global scope", name);
+ return false;
+ }
+
+ return true;
+}
+
+
+/* Record a #include or #include_next for PPH.
+ READER is the main pre-processor object, LOC is the location where
+ the #include is being emitted from, DNAME is the name of the
+ #include directive used, NAME is the canonical name of the file being
+ included, ANGLE_BRACKETS is non-zero if this #include uses <> and
+ TOK_P is a pointer to the current token being pre-processed. */
+
+static bool
+pph_include_handler (cpp_reader *reader,
+ location_t loc,
+ const unsigned char *dname,
+ const char *name,
+ int angle_brackets,
+ const cpp_token **tok_p ATTRIBUTE_UNUSED)
+{
+ const char *pph_file;
+ bool read_text_file_p;
+
+ if (flag_pph_tracer >= 1)
+ {
+ fprintf (pph_logfile, "PPH: #%s", dname);
+ fprintf (pph_logfile, " %c", angle_brackets ? '<' : '"');
+ fprintf (pph_logfile, "%s", name);
+ fprintf (pph_logfile, "%c\n", angle_brackets ? '>' : '"');
+ }
+
+ read_text_file_p = true;
+ pph_file = query_pph_include_map (name);
+ if (pph_file != NULL
+ && pph_is_valid_here (name, loc)
+ && !cpp_included_before (reader, name, input_location))
+ {
+ pph_stream *include;
+
+ /* Hack. We do this to mimic what the non-pph compiler does in
+ _cpp_stack_include as our goal is to have identical line_tables. */
+ line_table->highest_location--;
+
+ include = pph_read_file (pph_file);
+
+ /* If we are generating a new PPH image, add the stream we just
+ read to the list of includes. This way, the parser will be
+ able to resolve references to symbols in INCLUDE and its
+ children. */
+ if (pph_writer_enabled_p ())
+ pph_writer_add_include (include);
+
+ read_text_file_p = false;
+ }
+
+ return read_text_file_p;
+}
+
+
+/* PPH include tree dumper. Each entry in this file has the format:
+
+ DEPTH|SYSP|DNAME|CANONICAL-NAME|FULL-NAME|PPH-NAME
+
+ Where:
+ DEPTH is the include depth of the file.
+ SYSP 1 for a system header
+ 2 for a C system header that needs 'extern "C"'
+ 0 otherwise.
+ DNAME name of the #include directive used.
+ CANONICAL-NAME is the name of the file as specified by the
+ #include directive.
+ FULL-NAME is the full path name where the included file
+ was found by the pre-processor.
+ PPH-NAME is the name of the associated PPH file. */
+
+typedef struct {
+ /* Name of current #include directive. */
+ const unsigned char *dname;
+
+ /* Canonical name of file being included. */
+ const char *name;
+
+ /* Previous libcpp #include handler. */
+ void (*prev_file_change) (cpp_reader *, const struct line_map *);
+
+ /* Previous libcpp file change handler. */
+ bool (*prev_include) (cpp_reader *, source_location, const unsigned char *,
+ const char *, int, const cpp_token **);
+} pph_include_tree_dumper;
+
+static pph_include_tree_dumper tree_dumper;
+
+
+/* #include handler for libcpp. READER is the main pre-processor object,
+ LOC is the location where the #include is being emitted from, DNAME
+ is the name of the #include directive used, NAME is the canonical
+ name of the file being included, ANGLE_BRACKETS is non-zero if this
+ #include uses <> and TOK_P is a pointer to the current token being
+ pre-processed. */
+
+static bool
+pph_include_handler_for_map (cpp_reader *reader,
+ location_t loc,
+ const unsigned char *dname,
+ const char *name,
+ int angle_brackets,
+ const cpp_token **tok_p)
+{
+ bool retval = true;
+
+ if (tree_dumper.prev_include)
+ retval &= tree_dumper.prev_include (reader, loc, dname, name,
+ angle_brackets, tok_p);
+ tree_dumper.dname = dname;
+ tree_dumper.name = name;
+
+ return retval;
+}
+
+
+/* Return a copy of NAME with the characters '/' and '.' replaced with
+ '_'. The caller is reponsible for freeing the returned string. */
+
+static char *
+pph_flatten_name (const char *name)
+{
+ char *str = xstrdup (name);
+ size_t i;
+
+ for (i = 0; i < strlen (str); i++)
+ if (str[i] == DIR_SEPARATOR || str[i] == '.')
+ str[i] = '_';
+
+ return str;
+}
+
+
+/* File change handler for libcpp. READER is the main pre-processor object,
+ MAP is the line map entry for the file that we are entering into. */
+
+static void
+pph_file_change_handler (cpp_reader *reader, const struct line_map *map)
+{
+ char *flat;
+
+ if (tree_dumper.prev_file_change)
+ tree_dumper.prev_file_change (reader, map);
+
+ /* We are only interested in line maps that describe a new file being
+ entered. */
+ if (map == NULL || map->reason != LC_ENTER)
+ return;
+
+ /* Emit a line to the map file with the format:
+
+ DEPTH|SYSP|DNAME|CANONICAL-NAME|FULL-NAME|PPH-NAME
+ */
+ flat = pph_flatten_name (map->d.ordinary.to_file);
+ fprintf (stderr, "%d|%d|%s|%s|%s|%s.pph\n", line_table->depth,
+ map->d.ordinary.sysp, tree_dumper.dname, tree_dumper.name,
+ map->d.ordinary.to_file, flat);
+ free (flat);
+ tree_dumper.dname = NULL;
+ tree_dumper.name = NULL;
+}
+
+
+/* Initialize the #include tree dumper. */
+
+void
+pph_init_include_tree (void)
+{
+ cpp_callbacks *cb;
+
+ memset (&tree_dumper, 0, sizeof (tree_dumper));
+
+ if (pph_enabled_p ())
+ fatal_error ("do not use -fpph-map-gen with any other PPH flag");
+
+ /* Set up the libcpp handler for file change events. Each event
+ will generate a new entry in the map file. */
+ cb = cpp_get_callbacks (parse_in);
+
+ tree_dumper.prev_file_change = cb->file_change;
+ cb->file_change = pph_file_change_handler;
+
+ tree_dumper.prev_include = cb->include;
+ cb->include = pph_include_handler_for_map;
+}
+
+
+/* Add INCLUDE, and the images included by it, to the list of files
+ included by STREAM. */
+
+void
+pph_add_include (pph_stream *stream, pph_stream *include)
+{
+ pph_stream *include_child;
+ unsigned i;
+
+ include->parent = stream;
+ VEC_safe_push (pph_stream_ptr, heap, stream->includes, include);
+ FOR_EACH_VEC_ELT (pph_stream_ptr, include->includes, i, include_child)
+ VEC_safe_push (pph_stream_ptr, heap, stream->includes, include_child);
+}
+
+
+/*********************************************************** stream handling */
+
+
+/* List of PPH images opened for reading. Images opened during #include
+ processing and opened from pph_in_includes cannot be closed
+ immediately after reading, because the pickle cache contained in
+ them may be referenced from other images. We delay closing all of
+ them until the end of parsing (when pph_streamer_finish is called). */
+static VEC(pph_stream_ptr, heap) *pph_read_images = NULL;
+
+
+/* If FILENAME has already been read, return the stream associated with it. */
+
+static pph_stream *
+pph_find_stream_for (const char *filename)
+{
+ pph_stream *include;
+ unsigned i;
+
+ /* FIXME pph, implement a hash map to avoid this linear search. */
+ FOR_EACH_VEC_ELT (pph_stream_ptr, pph_read_images, i, include)
+ if (strcmp (include->name, filename) == 0)
+ return include;
+
+ return NULL;
+}
+
+
+/* Add STREAM to the list of read images. */
+
+void
+pph_mark_stream_read (pph_stream *stream)
+{
+ stream->in_memory_p = true;
+ VEC_safe_push (pph_stream_ptr, heap, pph_read_images, stream);
+}
+
+
+/* Create a new PPH stream to be stored on the file called NAME.
+ MODE is passed to fopen directly. */
+
+pph_stream *
+pph_stream_open (const char *name, const char *mode)
+{
+ pph_stream *stream;
+ FILE *f;
+
+ /* If we have already opened a PPH stream named NAME, just return
+ its associated stream. */
+ stream = pph_find_stream_for (name);
+ if (stream)
+ {
+ gcc_assert (stream->in_memory_p);
+ return stream;
+ }
+
+ f = fopen (name, mode);
+ if (!f)
+ return NULL;
+
+ stream = XCNEW (pph_stream);
+ stream->file = f;
+ stream->name = xstrdup (name);
+ stream->write_p = (strchr (mode, 'w') != NULL);
+ pph_cache_init (&stream->cache);
+ stream->preloaded_cache = pph_preloaded_cache;
+ if (stream->write_p)
+ pph_init_write (stream);
+ else
+ pph_init_read (stream);
+
+ return stream;
+}
+
+
+/* Close PPH stream STREAM. */
+
+void
+pph_stream_close (pph_stream *stream)
+{
+ /* STREAM can be NULL if it could not be properly opened. An error
+ has already been emitted, so avoid crashing here. */
+ if (stream == NULL)
+ return;
+
+ if (flag_pph_tracer >= 1)
+ fprintf (pph_logfile, "PPH: Closing %s\n", stream->name);
+
+ /* If we were writing to STREAM, flush all the memory buffers. This
+ does the actual writing of all the pickled data structures. */
+ if (stream->write_p)
+ pph_flush_buffers (stream);
+
+ fclose (stream->file);
+
+ /* Deallocate all memory used. */
+ stream->file = NULL;
+ VEC_free (pph_cache_entry, heap, stream->cache.v);
+ pointer_map_destroy (stream->cache.m);
+ VEC_free (pph_symtab_entry, heap, stream->symtab.v);
+ VEC_free (pph_stream_ptr, heap, stream->includes);
+
+ if (stream->write_p)
+ {
+ destroy_output_block (stream->encoder.w.ob);
+ free (stream->encoder.w.decl_state_stream);
+ lto_delete_out_decl_state (stream->encoder.w.out_state);
+ }
+ else
+ {
+ unsigned i;
+
+ free (stream->encoder.r.ib);
+ lto_data_in_delete (stream->encoder.r.data_in);
+ for (i = 0; i < PPH_NUM_SECTIONS; i++)
+ free (stream->encoder.r.pph_sections[i]);
+ free (stream->encoder.r.pph_sections);
+ free (stream->encoder.r.file_data);
+ }
+
+ free (stream);
+}
+
+
+/********************************************************** stream callbacks */
+
+
+/* Callback for writing ASTs to a stream. Write EXPR to the PPH stream
+ in OB. */
+
+static void
+pph_write_tree (struct output_block *ob, tree expr, bool ref_p ATTRIBUTE_UNUSED)
+{
+ pph_out_tree ((pph_stream *) ob->sdata, expr);
+}
+
+
+/* Callback for reading ASTs from a stream. Instantiate and return a
+ new tree from the PPH stream in DATA_IN. */
+
+static tree
+pph_read_tree (struct lto_input_block *ib ATTRIBUTE_UNUSED,
+ struct data_in *data_in)
+{
+ return pph_in_tree ((pph_stream *) data_in->sdata);
+}
+
+
+/* Callback for streamer_hooks.input_location. An offset is applied to
+ the location_t read in according to the properties of the merged
+ line_table. IB and DATA_IN are as in lto_input_location. This function
+ should only be called after pph_in_and_merge_line_table was called as
+ we expect pph_loc_offset to be set. */
+
+static location_t
+pph_input_location (struct lto_input_block *ib ATTRIBUTE_UNUSED,
+ struct data_in *data_in)
+{
+ return pph_in_location ((pph_stream *) data_in->sdata);
+}
+
+
+/* Callback for streamer_hooks.output_location. Output the LOC directly,
+ an offset will be applied on input after rebuilding the line_table.
+ OB and LOC are as in lto_output_location. */
+
+static void
+pph_output_location (struct output_block *ob, location_t loc)
+{
+ pph_out_location ((pph_stream *) ob->sdata, loc);
+}
+
+
+/******************************************************** pph initialization */
+
+
+/* Initialize all the streamer hooks used for streaming ASTs. */
+
+static void
+pph_hooks_init (void)
+{
+ streamer_hooks_init ();
+ streamer_hooks.write_tree = pph_write_tree;
+ streamer_hooks.read_tree = pph_read_tree;
+ streamer_hooks.input_location = pph_input_location;
+ streamer_hooks.output_location = pph_output_location;
+}
+
+
+/* Initialize the streamer. */
+
+static void
+pph_streamer_init (void)
+{
+ pph_hooks_init ();
+ pph_init_preloaded_cache ();
+}
+
+
+/* The initial order of the size of the lexical lookaside table,
+ which will accomodate as many as half of its slots in use. */
+
+static const unsigned int cpp_lt_order = /* 2 to the power of */ 9;
+
+/* Initialize PPH support. */
+
+void
+pph_init (void)
+{
+ cpp_callbacks *cb;
+ cpp_lookaside *table;
+
+ if (flag_pph_logfile)
+ {
+ pph_logfile = fopen (flag_pph_logfile, "w");
+ if (!pph_logfile)
+ fatal_error ("Cannot create %s for writing: %m", flag_pph_logfile);
+ }
+ else
+ pph_logfile = stdout;
+
+ if (flag_pph_tracer >= 1)
+ fprintf (pph_logfile, "PPH: Initializing.\n");
+
+ /* Set up the libcpp handler for #include. */
+ cb = cpp_get_callbacks (parse_in);
+ cb->include = pph_include_handler;
+
+ table = cpp_lt_exchange (parse_in,
+ cpp_lt_create (cpp_lt_order, flag_pph_debug/2));
+ gcc_assert (table == NULL);
+
+ pph_streamer_init ();
+
+ /* If we are generating a PPH file, initialize the writer. */
+ if (pph_writer_enabled_p ())
+ pph_writer_init ();
+
+ pph_reader_init ();
+}
+
+
+/********************************************************** pph finalization */
+
+
+/* Finalize the streamer. */
+
+static void
+pph_streamer_finish (void)
+{
+ unsigned i;
+ pph_stream *image;
+
+ /* Finalize the writer. */
+ pph_writer_finish ();
+
+ /* Finalize the reader. */
+ pph_reader_finish ();
+
+ /* Close any images read during parsing. */
+ FOR_EACH_VEC_ELT (pph_stream_ptr, pph_read_images, i, image)
+ pph_stream_close (image);
+
+ VEC_free (pph_stream_ptr, heap, pph_read_images);
+}
+
+
+/* Finalize PPH support. */
+
+void
+pph_finish (void)
+{
+ /* Finalize the streamer. */
+ pph_streamer_finish ();
+
+ /* Close log files. */
+ if (flag_pph_tracer >= 1)
+ fprintf (pph_logfile, "PPH: Finishing.\n");
+
+ if (flag_pph_logfile)
+ fclose (pph_logfile);
+}
Index: gcc/cp/Make-lang.in
===================================================================
--- gcc/cp/Make-lang.in (revision 181815)
+++ gcc/cp/Make-lang.in (working copy)
@@ -82,8 +82,8 @@ CXX_AND_OBJCXX_OBJS = cp/call.o cp/decl.
cp/typeck.o cp/cvt.o cp/except.o cp/friend.o cp/init.o cp/method.o \
cp/search.o cp/semantics.o cp/tree.o cp/repo.o cp/dump.o cp/optimize.o \
cp/mangle.o cp/cp-objcp-common.o cp/name-lookup.o cp/cxx-pretty-print.o \
- cp/cp-gimplify.o cp/pph.o cp/pph-streamer.o cp/pph-streamer-out.o \
- cp/pph-streamer-in.o tree-mudflap.o $(CXX_C_OBJS)
+ cp/cp-gimplify.o cp/pph-core.o cp/pph-out.o cp/pph-in.o \
+ tree-mudflap.o $(CXX_C_OBJS)
# Language-specific object files for C++.
CXX_OBJS = cp/cp-lang.o c-family/stub-objc.o $(CXX_AND_OBJCXX_OBJS)
@@ -265,8 +265,10 @@ CXX_TREE_H = $(TREE_H) cp/name-lookup.h
CXX_PARSER_H = tree.h c-family/c-pragma.h cp/parser.h
CXX_PRETTY_PRINT_H = cp/cxx-pretty-print.h $(C_PRETTY_PRINT_H)
CXX_PPH_H = $(CXX_TREE_H) cp/pph.h
-CXX_PPH_STREAMER_H = $(LTO_STREAMER_H) $(DATA_STREAMER_H) $(TREE_STREAMER_H) \
- $(TREE_H) $(CXX_PPH_H) cp/pph-streamer.h
+CXX_PPH_STREAMER_H = $(CXX_PPH_H) $(DATA_STREAMER_H) $(TREE_STREAMER_H) \
+ cp/pph-streamer.h
+CXX_PPH_COMMON_H = $(CONFIG_H) $(SYSTEM_H) coretypes.h $(CXX_PPH_STREAMER_H) \
+ $(TREE_PASS_H) tree-iterator.h version.h cppbuiltin.h $(CXX_PARSER_H)
cp/lex.o: cp/lex.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) \
$(C_PRAGMA_H) output.h input.h cp/operators.def $(TM_P_H) \
@@ -349,19 +351,8 @@ cp/name-lookup.o: cp/name-lookup.c $(CON
$(CXX_PPH_H) pointer-set.h
cp/cxx-pretty-print.o: cp/cxx-pretty-print.c $(CXX_PRETTY_PRINT_H) \
$(CONFIG_H) $(SYSTEM_H) $(TM_H) coretypes.h $(CXX_TREE_H) tree-pretty-print.h
-cp/pph.o: cp/pph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(CPPLIB_H) \
- toplev.h $(TREE_H) $(CXX_TREE_H) $(TIMEVAR_H) pointer-set.h \
- fixed-value.h $(TREE_PASS_H) $(TREE_INLINE_H) tree-pretty-print.h \
- $(CXX_PARSER_H) $(CXX_PPH_H) $(CXX_PPH_STREAMER_H)
-cp/pph-streamer.o: cp/pph-streamer.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TREE_H) tree-pretty-print.h $(LTO_STREAMER_H) $(CXX_PPH_STREAMER_H) \
- $(CXX_PPH_H) $(TREE_PASS_H) version.h cppbuiltin.h tree-iterator.h \
- $(STREAMER_HOOKS_H)
-cp/pph-streamer-out.o: cp/pph-streamer-out.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(TREE_H) tree-pretty-print.h $(LTO_STREAMER_H) \
- $(CXX_PPH_STREAMER_H) $(CXX_PPH_H) $(TREE_PASS_H) version.h \
- $(CXX_PARSER_H) cppbuiltin.h tree-iterator.h $(CGRAPH_H)
-cp/pph-streamer-in.o: cp/pph-streamer-in.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(TREE_H) tree-pretty-print.h $(LTO_STREAMER_H) \
- $(CXX_PPH_STREAMER_H) $(CXX_PPH_H) $(TREE_PASS_H) version.h \
- $(CXX_PARSER_H) cppbuiltin.h tree-iterator.h toplev.h
+cp/pph-core.o: cp/pph-core.c $(CXX_PPH_COMMON_H) $(CPPLIB_H) $(TIMEVAR_H) \
+ $(TREE_INLINE_H) tree-pretty-print.h fixed-value.h pointer-set.h \
+ toplev.h
+cp/pph-out.o: cp/pph-out.c $(CXX_PPH_COMMON_H) $(CGRAPH_H)
+cp/pph-in.o: cp/pph-in.c $(CXX_PPH_COMMON_H) pointer-set.h toplev.h
Index: gcc/cp/pph.c
===================================================================
--- gcc/cp/pph.c (revision 181815)
+++ gcc/cp/pph.c (working copy)
@@ -1,403 +0,0 @@
-/* Factored pre-parsed header (PPH) support for C++
- Copyright (C) 2010, 2011 Free Software Foundation, Inc.
- Contributed by Lawrence Crowl <crowl@google.com> and
- Diego Novillo <dnovillo@google.com>.
-
- This file is part of GCC.
-
- GCC 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 3, or (at your option)
- any later version.
-
- GCC 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 GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "pph.h"
-#include "cpplib.h"
-#include "toplev.h"
-#include "tree.h"
-#include "cp-tree.h"
-#include "timevar.h"
-#include "pointer-set.h"
-#include "fixed-value.h"
-#include "md5.h"
-#include "tree-pass.h"
-#include "tree-dump.h"
-#include "tree-inline.h"
-#include "tree-pretty-print.h"
-#include "cxx-pretty-print.h"
-#include "parser.h"
-#include "pph-streamer.h"
-
-/* Log file where PPH analysis is written to. Controlled by
- -fpph_logfile. If this flag is not given, stdout is used. */
-FILE *pph_logfile = NULL;
-
-/* Convert a checked tree_code CODE to a string. */
-
-const char *
-pph_tree_code_text (enum tree_code code)
-{
- gcc_assert (code < MAX_TREE_CODES);
- return tree_code_name[code];
-}
-
-
-/* Dump a location LOC to FILE. */
-
-void
-pph_dump_location (FILE *file, location_t loc)
-{
- expanded_location xloc = expand_location (loc);
- fprintf (file, "%s:%d", xloc.file, xloc.line);
-}
-
-/* Dump identifying information for a minimal DECL to FILE. */
-
-void
-pph_dump_min_decl (FILE *file, tree decl)
-{
- print_generic_expr (file, DECL_NAME (decl), 0);
- print_generic_expr (file, DECL_CONTEXT (decl), 0);
- pph_dump_location (file, DECL_SOURCE_LOCATION (decl));
-}
-
-/* Dump a complicated name for tree T to FILE using FLAGS.
- See TDF_* in tree-pass.h for flags. */
-
-void
-pph_dump_tree_name (FILE *file, tree t, int flags)
-{
- enum tree_code code = TREE_CODE (t);
- const char *text = pph_tree_code_text (code);
- if (DECL_P (t))
- fprintf (file, "%s %s\n", text, decl_as_string (t, flags));
- else if (TYPE_P (t))
- fprintf (file, "%s %s\n", text, type_as_string (t, flags));
- else if (EXPR_P (t))
- fprintf (file, "%s %s\n", text, expr_as_string (t, flags));
- else
- {
- fprintf (file, "%s ", text );
- print_generic_expr (file, t, flags);
- fprintf (file, "\n");
- }
-}
-
-
-/* Dump namespace NS for PPH. */
-
-void
-pph_dump_namespace (FILE *file, tree ns)
-{
- fprintf (file, "namespace ");
- pph_dump_tree_name (file, ns, 0);
- fprintf (file, "{\n");
- pph_dump_binding (file, NAMESPACE_LEVEL (ns));
- fprintf (file, "}\n");
-}
-
-
-/* Dump cp_binding_level LEVEL for PPH. */
-
-void
-pph_dump_binding (FILE *file, cp_binding_level *level)
-{
- tree t, next;
- pph_dump_chain (file, level->names);
- for (t = level->namespaces; t; t = next)
- {
- next = DECL_CHAIN (t);
- if (!DECL_IS_BUILTIN (t))
- pph_dump_namespace (file, t);
- }
-}
-
-
-/* Dump a CHAIN for PPH. */
-
-void
-pph_dump_chain (FILE *file, tree chain)
-{
- tree t, next;
- for (t = chain; t; t = next)
- {
- next = DECL_CHAIN (t);
- if (!DECL_IS_BUILTIN (t))
- pph_dump_tree_name (file, t, 0);
- }
-}
-
-
-/* Return true if PPH image NAME can be used at the point of inclusion
- (given by LOC). */
-
-static bool
-pph_is_valid_here (const char *name, location_t loc)
-{
- /* If we are inside a scope, reject the image. We could be inside a
- namespace or a structure which changes the parsing context for
- the original text file. */
- if (scope_chain->x_brace_nesting > 0)
- {
- error_at (loc, "PPH file %s not included at global scope", name);
- return false;
- }
-
- return true;
-}
-
-
-/* Record a #include or #include_next for PPH.
- READER is the main pre-processor object, LOC is the location where
- the #include is being emitted from, DNAME is the name of the
- #include directive used, NAME is the canonical name of the file being
- included, ANGLE_BRACKETS is non-zero if this #include uses <> and
- TOK_P is a pointer to the current token being pre-processed. */
-
-static bool
-pph_include_handler (cpp_reader *reader,
- location_t loc,
- const unsigned char *dname,
- const char *name,
- int angle_brackets,
- const cpp_token **tok_p ATTRIBUTE_UNUSED)
-{
- const char *pph_file;
- bool read_text_file_p;
-
- if (flag_pph_tracer >= 1)
- {
- fprintf (pph_logfile, "PPH: #%s", dname);
- fprintf (pph_logfile, " %c", angle_brackets ? '<' : '"');
- fprintf (pph_logfile, "%s", name);
- fprintf (pph_logfile, "%c\n", angle_brackets ? '>' : '"');
- }
-
- read_text_file_p = true;
- pph_file = query_pph_include_map (name);
- if (pph_file != NULL
- && pph_is_valid_here (name, loc)
- && !cpp_included_before (reader, name, input_location))
- {
- pph_stream *include;
-
- /* Hack. We do this to mimic what the non-pph compiler does in
- _cpp_stack_include as our goal is to have identical line_tables. */
- line_table->highest_location--;
-
- include = pph_read_file (pph_file);
-
- /* If we are generating a new PPH image, add the stream we just
- read to the list of includes. This way, the parser will be
- able to resolve references to symbols in INCLUDE and its
- children. */
- if (pph_writer_enabled_p ())
- pph_writer_add_include (include);
-
- read_text_file_p = false;
- }
-
- return read_text_file_p;
-}
-
-
-/* The initial order of the size of the lexical lookaside table,
- which will accomodate as many as half of its slots in use. */
-
-static const unsigned int cpp_lt_order = /* 2 to the power of */ 9;
-
-/* Initialize PPH support. */
-
-void
-pph_init (void)
-{
- cpp_callbacks *cb;
- cpp_lookaside *table;
-
- if (flag_pph_logfile)
- {
- pph_logfile = fopen (flag_pph_logfile, "w");
- if (!pph_logfile)
- fatal_error ("Cannot create %s for writing: %m", flag_pph_logfile);
- }
- else
- pph_logfile = stdout;
-
- if (flag_pph_tracer >= 1)
- fprintf (pph_logfile, "PPH: Initializing.\n");
-
- /* Set up the libcpp handler for #include. */
- cb = cpp_get_callbacks (parse_in);
- cb->include = pph_include_handler;
-
- table = cpp_lt_exchange (parse_in,
- cpp_lt_create (cpp_lt_order, flag_pph_debug/2));
- gcc_assert (table == NULL);
-
- pph_streamer_init ();
-
- /* If we are generating a PPH file, initialize the writer. */
- if (pph_writer_enabled_p ())
- pph_writer_init ();
-
- pph_reader_init ();
-}
-
-
-/* Finalize PPH support. */
-
-void
-pph_finish (void)
-{
- /* Finalize the streamer. */
- pph_streamer_finish ();
-
- /* Close log files. */
- if (flag_pph_tracer >= 1)
- fprintf (pph_logfile, "PPH: Finishing.\n");
-
- if (flag_pph_logfile)
- fclose (pph_logfile);
-}
-
-
-/* PPH include tree dumper. Each entry in this file has the format:
-
- DEPTH|SYSP|DNAME|CANONICAL-NAME|FULL-NAME|PPH-NAME
-
- Where:
- DEPTH is the include depth of the file.
- SYSP 1 for a system header
- 2 for a C system header that needs 'extern "C"'
- 0 otherwise.
- DNAME name of the #include directive used.
- CANONICAL-NAME is the name of the file as specified by the
- #include directive.
- FULL-NAME is the full path name where the included file
- was found by the pre-processor.
- PPH-NAME is the name of the associated PPH file. */
-typedef struct {
- /* Name of current #include directive. */
- const unsigned char *dname;
-
- /* Canonical name of file being included. */
- const char *name;
-
- /* Previous libcpp #include handler. */
- void (*prev_file_change) (cpp_reader *, const struct line_map *);
-
- /* Previous libcpp file change handler. */
- bool (*prev_include) (cpp_reader *, source_location, const unsigned char *,
- const char *, int, const cpp_token **);
-} pph_include_tree_dumper;
-
-static pph_include_tree_dumper tree_dumper;
-
-
-/* Return a copy of NAME with the characters '/' and '.' replaced with
- '_'. The caller is reponsible for freeing the returned string. */
-
-static char *
-flatten_name (const char *name)
-{
- char *str = xstrdup (name);
- size_t i;
-
- for (i = 0; i < strlen (str); i++)
- if (str[i] == DIR_SEPARATOR || str[i] == '.')
- str[i] = '_';
-
- return str;
-}
-
-
-/* File change handler for libcpp. READER is the main pre-processor object,
- MAP is the line map entry for the file that we are entering into. */
-
-static void
-pph_file_change_handler (cpp_reader *reader, const struct line_map *map)
-{
- char *flat;
-
- if (tree_dumper.prev_file_change)
- tree_dumper.prev_file_change (reader, map);
-
- /* We are only interested in line maps that describe a new file being
- entered. */
- if (map == NULL || map->reason != LC_ENTER)
- return;
-
- /* Emit a line to the map file with the format:
-
- DEPTH|SYSP|DNAME|CANONICAL-NAME|FULL-NAME|PPH-NAME
- */
- flat = flatten_name (map->d.ordinary.to_file);
- fprintf (stderr, "%d|%d|%s|%s|%s|%s.pph\n", line_table->depth,
- map->d.ordinary.sysp, tree_dumper.dname, tree_dumper.name,
- map->d.ordinary.to_file, flat);
- free (flat);
- tree_dumper.dname = NULL;
- tree_dumper.name = NULL;
-}
-
-
-/* #include handler for libcpp. READER is the main pre-processor object,
- LOC is the location where the #include is being emitted from, DNAME
- is the name of the #include directive used, NAME is the canonical
- name of the file being included, ANGLE_BRACKETS is non-zero if this
- #include uses <> and TOK_P is a pointer to the current token being
- pre-processed. */
-
-static bool
-pph_include_handler_for_map (cpp_reader *reader,
- location_t loc,
- const unsigned char *dname,
- const char *name,
- int angle_brackets,
- const cpp_token **tok_p)
-{
- bool retval = true;
-
- if (tree_dumper.prev_include)
- retval &= tree_dumper.prev_include (reader, loc, dname, name,
- angle_brackets, tok_p);
- tree_dumper.dname = dname;
- tree_dumper.name = name;
-
- return retval;
-}
-
-
-/* Initialize the #include tree dumper. */
-
-void
-pph_init_include_tree (void)
-{
- cpp_callbacks *cb;
-
- memset (&tree_dumper, 0, sizeof (tree_dumper));
-
- if (pph_enabled_p ())
- fatal_error ("do not use -fpph-map-gen with any other PPH flag");
-
- /* Set up the libcpp handler for file change events. Each event
- will generate a new entry in the map file. */
- cb = cpp_get_callbacks (parse_in);
-
- tree_dumper.prev_file_change = cb->file_change;
- cb->file_change = pph_file_change_handler;
-
- tree_dumper.prev_include = cb->include;
- cb->include = pph_include_handler_for_map;
-}
Index: gcc/cp/pph.h
===================================================================
--- gcc/cp/pph.h (revision 181815)
+++ gcc/cp/pph.h (working copy)
@@ -137,14 +137,14 @@ extern FILE *pph_logfile;
/* Extern functions. */
-/* In pph.c */
+/* In pph-core.c */
extern void pph_init (void);
extern void pph_finish (void);
extern void pph_dump_location (FILE *file, location_t loc);
extern void pph_dump_tree_name (FILE *file, tree t, int flags);
extern void pph_init_include_tree (void);
-/* In pph-streamer-out.c. */
+/* In pph-out.c. */
extern void pph_out_uint (pph_stream *stream, unsigned int value);
extern void pph_out_location (pph_stream *stream, location_t loc);
extern void pph_out_tree (pph_stream *stream, tree t);
@@ -152,7 +152,7 @@ extern void pph_out_record_marker (pph_s
enum pph_record_marker marker, enum pph_tag tag);
void pph_add_decl_to_symtab (tree, enum pph_symtab_action, bool, bool);
-/* In pph-streamer-in.c. */
+/* In pph-in.c. */
extern unsigned int pph_in_uint (pph_stream *stream);
extern location_t pph_in_location (pph_stream *stream);
extern tree pph_in_tree (pph_stream *stream);
Index: gcc/cp/pph-streamer-in.c
===================================================================
--- gcc/cp/pph-streamer-in.c (revision 181815)
+++ gcc/cp/pph-streamer-in.c (working copy)
@@ -1,2728 +0,0 @@
-/* Routines for reading PPH data.
- Copyright (C) 2011 Free Software Foundation, Inc.
- Contributed by Diego Novillo <dnovillo@google.com>.
-
- This file is part of GCC.
-
- GCC 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 3, or (at your option)
- any later version.
-
- GCC 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 GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "pph.h"
-#include "tree.h"
-#include "langhooks.h"
-#include "tree-iterator.h"
-#include "tree-pretty-print.h"
-#include "lto-streamer.h"
-#include "pph-streamer.h"
-#include "tree-pass.h"
-#include "version.h"
-#include "cppbuiltin.h"
-#include "toplev.h"
-#include "parser.h"
-#include "pointer-set.h"
-
-
-/********************************************************* type declarations */
-
-
-typedef char *char_p;
-DEF_VEC_P(char_p);
-DEF_VEC_ALLOC_P(char_p,heap);
-
-
-/****************************************************** forward declarations */
-
-
-/* Forward declarations to avoid circularity. */
-static tree pph_in_merge_key_tree (pph_stream *, tree *);
-
-
-/***************************************************** stream initialization */
-
-
-/* String tables for all input streams. These are allocated separately
- from streams because they cannot be deallocated after the streams
- have been read (string streaming works by pointing into these
- tables).
-
- Each stream will create a new entry in this table of tables. The
- memory will remain allocated until the end of compilation. */
-static VEC(char_p,heap) *string_tables = NULL;
-
-
-/* Read into memory the contents of the file in STREAM. Initialize
- internal tables and data structures needed to re-construct the
- ASTs in the file. */
-
-void
-pph_init_read (pph_stream *stream)
-{
- struct stat st;
- size_t i, bytes_read, strtab_size, body_size;
- int retcode;
- pph_file_header *header;
- const char *strtab, *body;
- char *new_strtab;
-
- /* Read STREAM->NAME into the memory buffer stream->encoder.r.file_data. */
- retcode = fstat (fileno (stream->file), &st);
- gcc_assert (retcode == 0);
- stream->encoder.r.file_size = (size_t) st.st_size;
- stream->encoder.r.file_data = XCNEWVEC (char, stream->encoder.r.file_size);
- bytes_read = fread (stream->encoder.r.file_data, 1,
- stream->encoder.r.file_size, stream->file);
- gcc_assert (bytes_read == stream->encoder.r.file_size);
-
- /* Set up the file sections, header, body and string table for the
- low-level streaming routines. */
- stream->encoder.r.pph_sections = XCNEWVEC (struct lto_file_decl_data *,
- PPH_NUM_SECTIONS);
- for (i = 0; i < PPH_NUM_SECTIONS; i++)
- stream->encoder.r.pph_sections[i] = XCNEW (struct lto_file_decl_data);
-
- header = (pph_file_header *) stream->encoder.r.file_data;
- strtab = (const char *) header + sizeof (pph_file_header);
- strtab_size = header->strtab_size;
- body = strtab + strtab_size;
- gcc_assert (stream->encoder.r.file_size
- >= strtab_size + sizeof (pph_file_header));
- body_size = stream->encoder.r.file_size
- - strtab_size - sizeof (pph_file_header);
-
- /* Create a new string table for STREAM. This table is not part of
- STREAM because it needs to remain around until the end of
- compilation (all the string streaming routines work by pointing
- into the string table, so we cannot deallocate it after reading
- STREAM). */
- new_strtab = XNEWVEC (char, strtab_size);
- memcpy (new_strtab, strtab, strtab_size);
- VEC_safe_push (char_p, heap, string_tables, new_strtab);
-
- /* Create an input block structure pointing right after the string
- table. */
- stream->encoder.r.ib = XCNEW (struct lto_input_block);
- LTO_INIT_INPUT_BLOCK_PTR (stream->encoder.r.ib, body, 0, body_size);
- stream->encoder.r.data_in
- = lto_data_in_create (stream->encoder.r.pph_sections[0],
- new_strtab, strtab_size, NULL);
-
- /* Associate STREAM with STREAM->ENCODER.R.DATA_IN so we can recover
- it from the streamer hooks. */
- stream->encoder.r.data_in->sdata = (void *) stream;
-}
-
-
-/********************************************************** primitive values */
-
-
-/* Read an unsigned char VALUE to STREAM. */
-
-static unsigned char
-pph_in_uchar (pph_stream *stream)
-{
- unsigned char n = streamer_read_uchar (stream->encoder.r.ib);
- return n;
-}
-
-
-/* Read a HOST_WIDE_INT from STREAM. */
-
-static inline HOST_WIDE_INT
-pph_in_hwi (pph_stream *stream)
-{
- return streamer_read_hwi (stream->encoder.r.ib);
-}
-
-
-/* Read an int from STREAM. */
-
-static inline int
-pph_in_int (pph_stream *stream)
-{
- HOST_WIDE_INT n = streamer_read_hwi (stream->encoder.r.ib);
- gcc_assert (n == (int) n);
- return (int) n;
-}
-
-
-/* Read an unsigned HOST_WIDE_INT from STREAM. */
-
-static inline unsigned HOST_WIDE_INT
-pph_in_uhwi (pph_stream *stream)
-{
- return streamer_read_uhwi (stream->encoder.r.ib);
-}
-
-
-/* Read an unsigned integer from STREAM. */
-
-unsigned int
-pph_in_uint (pph_stream *stream)
-{
- HOST_WIDE_INT unsigned n = streamer_read_uhwi (stream->encoder.r.ib);
- gcc_assert (n == (unsigned) n);
- return (unsigned) n;
-}
-
-
-/* Read N bytes from STREAM into P. The caller is responsible for
- allocating a sufficiently large buffer. */
-
-static void
-pph_in_bytes (pph_stream *stream, void *p, size_t n)
-{
- lto_input_data_block (stream->encoder.r.ib, p, n);
-}
-
-
-/* Read and return a string from STREAM. */
-
-static const char *
-pph_in_string (pph_stream *stream)
-{
- const char *s = streamer_read_string (stream->encoder.r.data_in,
- stream->encoder.r.ib);
- return s;
-}
-
-
-/* Read a bitpack from STREAM. */
-
-static struct bitpack_d
-pph_in_bitpack (pph_stream *stream)
-{
- struct bitpack_d bp = streamer_read_bitpack (stream->encoder.r.ib);
- return bp;
-}
-
-
-/******************************************************** source information */
-
-
-/* Set in pph_in_and_merge_line_table. Represents the source_location offset
- which every streamed in token must add to it's serialized source_location.
-
- FIXME pph: Ideally this would be in pph_stream.encoder.r, but for that we
- first need to get rid of the dependency to the streamer_hook for locations.
- */
-static int pph_loc_offset;
-
-
-/* Read a linenum_type from STREAM. */
-
-static inline linenum_type
-pph_in_linenum_type (pph_stream *stream)
-{
- return (linenum_type) pph_in_uint (stream);
-}
-
-
-/* Read a source_location from STREAM. */
-
-static inline source_location
-pph_in_source_location (pph_stream *stream)
-{
- return (source_location) pph_in_uint (stream);
-}
-
-
-/* Read a line table marker from STREAM. */
-
-static inline enum pph_linetable_marker
-pph_in_linetable_marker (pph_stream *stream)
-{
- enum pph_linetable_marker m =
- (enum pph_linetable_marker) pph_in_uchar (stream);
- gcc_assert (m == PPH_LINETABLE_ENTRY
- || m == PPH_LINETABLE_REFERENCE
- || m == PPH_LINETABLE_END);
- return m;
-}
-
-
-
-/* Read all the fields of struct line_map LM from STREAM. LM is assumed
- to be an ordinary line map. */
-
-static void
-pph_in_line_map_ordinary (pph_stream *stream, struct line_map *lm)
-{
- struct bitpack_d bp;
-
- ORDINARY_MAP_FILE_NAME (lm) = pph_in_string (stream);
- ORDINARY_MAP_STARTING_LINE_NUMBER (lm) = pph_in_linenum_type (stream);
-
- /* Note that this index is an offset indicating the distance from LM
- to the line map entry for LM's includer. It needs to be adjusted
- while reading the line table in pph_in_line_table_and_includes. */
- ORDINARY_MAP_INCLUDER_FILE_INDEX (lm) = pph_in_int (stream);
- bp = pph_in_bitpack (stream);
- ORDINARY_MAP_IN_SYSTEM_HEADER_P (lm)
- = (unsigned char) bp_unpack_value (&bp, CHAR_BIT);
- ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (lm) = bp_unpack_value (&bp,
- COLUMN_BITS_BIT);
-}
-
-
-/* Read a line_map from STREAM into LM. */
-
-static void
-pph_in_line_map (pph_stream *stream, struct line_map *lm)
-{
- struct lto_input_block *ib = stream->encoder.r.ib;
-
- lm->start_location = pph_in_source_location (stream);
- lm->reason = streamer_read_enum (ib, lc_reason, LC_ENTER_MACRO);
-
- /* FIXME pph. We currently do not support location tracking for
- macros in PPH images. */
- gcc_assert (lm->reason != LC_ENTER_MACRO);
- pph_in_line_map_ordinary (stream, lm);
-}
-
-
-/* Read in from STREAM and merge a referenced include into the current parsing
- context. */
-
-static void
-pph_in_include (pph_stream *stream)
-{
- int old_loc_offset;
- const char *include_name;
- pph_stream *include_stream;
- source_location prev_start_loc = pph_in_source_location (stream);
-
- /* Simulate highest_location to be as it would be at this point in a non-pph
- compilation. */
- line_table->highest_location = (prev_start_loc - 1) + pph_loc_offset;
-
- /* FIXME pph: If we move pph_loc_offset to pph_stream.encoder.r, we could
- have an independent offset for each stream and not have to save and
- restore the state of a global pph_loc_offset as we are doing here. */
- old_loc_offset = pph_loc_offset;
-
- include_name = pph_in_string (stream);
- include_stream = pph_read_file (include_name);
-
- /* Add INCLUDE_STREAM, and the images included by it, to the list
- of included images for STREAM. */
- pph_add_include (stream, include_stream);
-
- pph_loc_offset = old_loc_offset;
-}
-
-
-/* Read the line_table from STREAM and merge it in the current
- line_table. At the same time load includes in the order they were
- originally included by loading them at the point they were
- referenced in the line_table.
-
- Returns the source_location of line 1 / col 0 for this include. */
-
-static source_location
-pph_in_line_table_and_includes (pph_stream *stream)
-{
- unsigned int used_before, old_depth;
- bool first;
- enum pph_linetable_marker next_lt_marker;
- int top_includer_ix;
-
- used_before = LINEMAPS_ORDINARY_USED (line_table);
- first = true;
-
- /* All line map entries that have -1 as the includer, will now be
- relocated to the current last line map entry in the line table. */
- top_includer_ix = used_before - 1;
-
- for (next_lt_marker = pph_in_linetable_marker (stream);
- next_lt_marker != PPH_LINETABLE_END;
- next_lt_marker = pph_in_linetable_marker (stream))
- {
- if (next_lt_marker == PPH_LINETABLE_REFERENCE)
- {
- gcc_assert (!first);
- pph_in_include (stream);
- }
- else
- {
- struct line_map *lm;
- int last_entry_ix;
-
- lm = linemap_new_map (line_table, LC_ENTER);
- pph_in_line_map (stream, lm);
-
- /* All the entries that we read from STREAM will be appended
- to the end of line_table. Calculate the index for the
- last entry so that we can resolve the relative indices
- for all the includer file index entries we read from
- STREAM. Note that LAST_ENTRY_IX is the index of the line
- map LM that we have just read. */
- last_entry_ix = LINEMAPS_ORDINARY_USED (line_table) - 1;
-
- if (first)
- {
- first = false;
- pph_loc_offset = (line_table->highest_location + 1)
- - lm->start_location;
- gcc_assert (ORDINARY_MAP_INCLUDER_FILE_INDEX (lm) == -1);
- }
-
- /* Relocate the includer file index. For most entries, the
- writer wrote ORDINARY_MAP_INCLUDER_FILE_INDEX as a
- relative offset between this entry and the original
- includer file index (see pph_out_line_map_ordinary).
- Convert that relative index into an absolute index in the
- current line_table.
-
- A relocation value of -1 means that line map LM is
- included by the current top includer (i.e., STREAM), so
- we use the value TOP_INCLUDER_IX for it. */
- if (ORDINARY_MAP_INCLUDER_FILE_INDEX (lm) == -1)
- ORDINARY_MAP_INCLUDER_FILE_INDEX (lm) = top_includer_ix;
- else
- ORDINARY_MAP_INCLUDER_FILE_INDEX (lm) -= last_entry_ix;
-
- lm->start_location += pph_loc_offset;
- }
- }
-
- /* We used to expect exactly the same number of entries, but files
- included from this PPH file may sometimes not be needed. For
- example,
-
- #include "2.pph"
- #include "foo.pph"
- +--> #include "1.pph"
- #include "2.pph"
- #include "3.pph"
-
- When foo.pph was originally created, the line table was built
- with inclusions of 1.pph, 2.pph and 3.pph. But when compiling
- the main translation unit, we include 2.pph before foo.pph, so
- the inclusion of 2.pph from foo.pph does nothing. Leaving the
- line table in a different shape than the original compilation.
-
- Instead of insisting on getting EXPECTED_IN entries, we expect at
- most EXPECTED_IN entries. */
- {
- unsigned int expected = pph_in_uint (stream);
- gcc_assert (LINEMAPS_ORDINARY_USED (line_table) - used_before <= expected);
- }
-
- line_table->highest_location = pph_loc_offset + pph_in_uint (stream);
- line_table->highest_line = pph_loc_offset + pph_in_uint (stream);
-
- /* The MAX_COLUMN_HINT can be directly overwritten. */
- line_table->max_column_hint = pph_in_uint (stream);
-
- /* The line_table doesn't store the last LC_LEAVE in any given compilation;
- thus we need to replay the LC_LEAVE for the header now. For that same
- reason, the line_table should currently be in a state representing a depth
- one include deeper then the depth at which this pph was included. The
- LC_LEAVE replay will then bring the depth back to what it was before
- calling this function. */
- old_depth = line_table->depth++;
- linemap_add (line_table, LC_LEAVE, 0, NULL, 0);
- gcc_assert (line_table->depth == old_depth);
-
- return MAP_START_LOCATION (LINEMAPS_ORDINARY_MAP_AT (line_table, used_before));
-}
-
-
-/*********************************************************** record handling */
-
-
-/* Wrapper for memory allocation calls that should have their results
- registered in the PPH streamer cache. DATA is the pointer returned
- by the memory allocation call in ALLOC_EXPR. IX is the cache slot
- in CACHE where the newly allocated DATA should be registered at. */
-#define ALLOC_AND_REGISTER(CACHE, IX, TAG, DATA, ALLOC_EXPR) \
- do { \
- (DATA) = (ALLOC_EXPR); \
- pph_cache_insert_at (CACHE, DATA, IX, TAG); \
- } while (0)
-
-
-/* Read and return a record marker from STREAM. On return, *TAG_P will
- contain the tag for the data type stored in this record. */
-enum pph_record_marker
-pph_in_record_marker (pph_stream *stream, enum pph_tag *tag_p)
-{
- enum pph_record_marker m = (enum pph_record_marker) pph_in_uchar (stream);
- gcc_assert (m == PPH_RECORD_START
- || m == PPH_RECORD_START_NO_CACHE
- || m == PPH_RECORD_START_MUTATED
- || m == PPH_RECORD_START_MERGE_KEY
- || m == PPH_RECORD_START_MERGE_BODY
- || m == PPH_RECORD_END
- || m == PPH_RECORD_IREF
- || m == PPH_RECORD_XREF
- || m == PPH_RECORD_PREF);
-
- *tag_p = (enum pph_tag) pph_in_uint (stream);
- gcc_assert ((unsigned) *tag_p < (unsigned) PPH_NUM_TAGS);
-
- if (flag_pph_tracer >= 5)
- pph_trace_marker (m, *tag_p);
-
- return m;
-}
-
-
-/* Read and return a record header from STREAM. EXPECTED_TAG indicates
- the data type that should be stored in this record. When a
- PPH_RECORD_START marker is read, the next word read is an index
- into the streamer cache where the rematerialized data structure
- should be stored. When the writer stored this data structure for
- the first time, it added it to its own streamer cache at slot
- number *CACHE_IX_P.
-
- This way, if the same data structure was written a second time to
- the stream, instead of writing the whole structure again, only the
- index *CACHE_IX_P is written as a PPH_RECORD_IREF record.
-
- Therefore, when reading a PPH_RECORD_START marker, *CACHE_IX_P will
- contain the slot number where the materialized data should be
- cached at. When reading a PPH_RECORD_IREF marker, *CACHE_IX_P will
- contain the slot number the reader can find the previously
- materialized structure.
-
- If the record starts with PPH_RECORD_XREF, this means that the data
- we are about to read is located in the pickle cache of one of
- STREAM's included images. In this case, the record consists of two
- indices: the first one (*INCLUDE_IX_P) indicates which included
- image contains the data (it is an index into STREAM->INCLUDES), the
- second one indicates which slot in that image's pickle cache we can
- find the data. */
-
-static inline enum pph_record_marker
-pph_in_start_record (pph_stream *stream, unsigned *include_ix_p,
- unsigned *cache_ix_p, enum pph_tag expected_tag)
-{
- enum pph_tag read_tag;
- enum pph_record_marker marker = pph_in_record_marker (stream, &read_tag);
-
- /* If the caller expects any tree, make sure we get a valid tree code. */
- if (expected_tag == PPH_any_tree)
- gcc_assert (read_tag < PPH_any_tree);
- else
- gcc_assert (read_tag == expected_tag);
-
- *include_ix_p = (unsigned) -1;
- *cache_ix_p = (unsigned) -1;
-
- /* For PPH_RECORD_START and PPH_RECORD_IREF markers, read the
- streamer cache slot where we should store or find the
- rematerialized data structure (see description above).
- Also read the preloaded cache slot in IX for PPH_RECORD_PREF. */
- if (marker == PPH_RECORD_START
- || marker == PPH_RECORD_IREF
- || marker == PPH_RECORD_PREF
- || marker == PPH_RECORD_START_MERGE_BODY
- || marker == PPH_RECORD_START_MERGE_KEY)
- *cache_ix_p = pph_in_uint (stream);
- else if (marker == PPH_RECORD_XREF
- || marker == PPH_RECORD_START_MUTATED)
- {
- *include_ix_p = pph_in_uint (stream);
- *cache_ix_p = pph_in_uint (stream);
- }
- else if (marker == PPH_RECORD_END || marker == PPH_RECORD_START_NO_CACHE)
- ; /* Nothing to do. This record will not need cache updates. */
- else
- gcc_unreachable ();
-
- return marker;
-}
-
-
-/********************************************************** lexical elements */
-
-
-/* Read and return a location_t from STREAM. */
-
-location_t
-pph_in_location (pph_stream *stream)
-{
- struct bitpack_d bp;
- bool is_builtin;
- unsigned HOST_WIDE_INT n;
- location_t old_loc;
-
- bp = pph_in_bitpack (stream);
- is_builtin = bp_unpack_value (&bp, 1);
-
- n = pph_in_uhwi (stream);
- old_loc = (location_t) n;
- gcc_assert (old_loc == n);
-
- return is_builtin ? old_loc : old_loc + pph_loc_offset;
-}
-
-
-/* Load the tree value associated with TOKEN from STREAM. */
-
-static void
-pph_in_token_value (pph_stream *stream, cp_token *token)
-{
- switch (token->type)
- {
- case CPP_TEMPLATE_ID:
- case CPP_NESTED_NAME_SPECIFIER:
- /* FIXME pph - Need to handle struct tree_check. */
- break;
-
- case CPP_KEYWORD:
- token->u.value = ridpointers[token->keyword];
- break;
-
- case CPP_NAME:
- case CPP_CHAR:
- case CPP_WCHAR:
- case CPP_CHAR16:
- case CPP_CHAR32:
- case CPP_NUMBER:
- case CPP_STRING:
- case CPP_WSTRING:
- case CPP_STRING16:
- case CPP_STRING32:
- token->u.value = pph_in_tree (stream);
- break;
-
- case CPP_PRAGMA:
- /* Nothing to do. Field pragma_kind has already been loaded. */
- break;
-
- default:
- pph_in_bytes (stream, &token->u.value, sizeof (token->u.value));
- gcc_assert (token->u.value == NULL);
- }
-}
-
-
-/* Read and return a token from STREAM. */
-
-static cp_token *
-pph_in_token (pph_stream *stream)
-{
- cp_token *token = ggc_alloc_cleared_cp_token ();
-
- /* Do not read the whole structure, the token value has
- dynamic size as it contains swizzled pointers.
- FIXME pph, restructure to allow bulk reads of the whole
- section. */
- pph_in_bytes (stream, token, sizeof (cp_token) - sizeof (void *));
-
- /* FIXME pph. Use an arbitrary (but valid) location to avoid
- confusing the rest of the compiler for now. */
- token->location = input_location;
-
- /* FIXME pph: verify that pph_in_token_value works with no tokens. */
- pph_in_token_value (stream, token);
-
- return token;
-}
-
-
-/* Read and return a cp_token_cache instance from STREAM. */
-
-static cp_token_cache *
-pph_in_token_cache (pph_stream *stream)
-{
- unsigned i, num;
- cp_token *first, *last;
-
- num = pph_in_uint (stream);
- for (last = first = NULL, i = 0; i < num; i++)
- {
- last = pph_in_token (stream);
- if (first == NULL)
- first = last;
- }
-
- return cp_token_cache_new (first, last);
-}
-
-
-/******************************************************************* vectors */
-
-
-/* Read and return a gc VEC of trees from STREAM. */
-
-static VEC(tree,gc) *
-pph_in_tree_vec (pph_stream *stream)
-{
- HOST_WIDE_INT i, num;
- VEC(tree,gc) *v;
-
- num = pph_in_hwi (stream);
- v = NULL;
- for (i = 0; i < num; i++)
- {
- tree t = pph_in_tree (stream);
- VEC_safe_push (tree, gc, v, t);
- }
-
- return v;
-}
-
-
-/* Read and return a gc VEC of qualified_typedef_usage_t from STREAM. */
-
-static VEC(qualified_typedef_usage_t,gc) *
-pph_in_qual_use_vec (pph_stream *stream)
-{
- unsigned i, num;
- VEC(qualified_typedef_usage_t,gc) *v;
-
- num = pph_in_uint (stream);
- v = NULL;
- for (i = 0; i < num; i++)
- {
- qualified_typedef_usage_t q;
- q.typedef_decl = pph_in_tree (stream);
- q.context = pph_in_tree (stream);
- q.locus = pph_in_location (stream);
- VEC_safe_push (qualified_typedef_usage_t, gc, v, &q);
- }
-
- return v;
-}
-
-
-/* Read the vector V of tree_pair_s instances from STREAM. */
-
-static VEC(tree_pair_s,gc) *
-pph_in_tree_pair_vec (pph_stream *stream)
-{
- unsigned i, num;
- VEC(tree_pair_s,gc) *v;
-
- num = pph_in_uint (stream);
- for (i = 0, v = NULL; i < num; i++)
- {
- tree_pair_s p;
- p.purpose = pph_in_tree (stream);
- p.value = pph_in_tree (stream);
- VEC_safe_push (tree_pair_s, gc, v, &p);
- }
-
- return v;
-}
-
-
-/* Test whether tree T is an element of vector V. */
-
-static bool
-pph_is_tree_element_of_vec (tree t, VEC(tree,gc) *v)
-{
- unsigned i;
- tree s;
- FOR_EACH_VEC_ELT (tree, v, i, s)
- if (s == t)
- return true;
- return false;
-}
-
-
-/* Return the union of two tree vecs. The argument vectors are unmodified. */
-
-static VEC(tree,gc) *
-pph_union_two_tree_vecs (VEC(tree,gc) *left, VEC(tree,gc) *right)
-{
- /* FIXME pph: This O(left)+O(left*right) union may become a problem.
- In the long run, we probably want to copy both into a hash table
- and then copy the table into the result. */
- unsigned i;
- tree t;
- VEC(tree,gc) *unioned = VEC_copy (tree, gc, left);
- FOR_EACH_VEC_ELT (tree, right, i, t)
- {
- if (!pph_is_tree_element_of_vec (t, left))
- VEC_safe_push (tree, gc, unioned, t);
- }
- return unioned;
-}
-
-
-/* Union FROM one tree vec with and INTO a tree vec. The INTO argument will
- have an updated value. The FROM argument is no longer valid. */
-
-static void
-pph_union_into_tree_vec (VEC(tree,gc) **into, VEC(tree,gc) *from)
-{
- if (!VEC_empty (tree, from))
- {
- if (*into == NULL)
- *into = from;
- else if (VEC_empty (tree, *into))
- {
- VEC_free (tree, gc, *into);
- *into = from;
- }
- else
- {
- VEC(tree,gc) *unioned = pph_union_two_tree_vecs (*into, from);
- VEC_free (tree, gc, *into);
- VEC_free (tree, gc, from);
- *into = unioned;
- }
- }
-}
-
-
-/******************************************************************** chains */
-
-
-/* Read a chain of ASTs from STREAM. */
-
-static tree
-pph_in_chain (pph_stream *stream)
-{
- return streamer_read_chain (stream->encoder.r.ib, stream->encoder.r.data_in);
-}
-
-
-/* Read a chain of AST merge keys from STREAM. Merge each tree
- into *CHAIN. */
-
-static void
-pph_in_merge_key_chain (pph_stream *stream, tree *chain)
-{
- unsigned i;
- HOST_WIDE_INT count;
-
- count = pph_in_hwi (stream);
- for (i = 0; i < count; i++)
- pph_in_merge_key_tree (stream, chain);
-}
-
-
-/* Read a chain of AST merge bodies from STREAM. */
-
-static void
-pph_in_merge_body_chain (pph_stream *stream)
-{
- unsigned i;
- HOST_WIDE_INT count;
-
- count = pph_in_hwi (stream);
- for (i = 0; i < count; i++)
- pph_in_tree (stream);
-}
-
-
-/* Merge table of contents. This TOC is used to decide whether a
- symbol has already been merged into a given compilation context.
- Compilation contexts are usually tree chains (e.g.,
- scope_chain->bindings->names), but they can be any stable memory
- address.
-
- This TOC is indexed by two values: the merge key read by
- pph_in_merge_key_tree and the context in which we are doing this
- merge. */
-static htab_t merge_toc = NULL;
-
-/* Table of contents entry. */
-typedef struct {
- /* Tree being matched. */
- tree expr;
-
- /* Context where this tree should be inserted into. */
- tree *context;
-
- /* Name of the tree (from pph_merge_name). */
- const char *name;
-} merge_toc_entry;
-
-
-/* Hash and equivalence functions for the merge TOC. */
-
-static hashval_t
-htab_merge_key_hash (const void *p)
-{
- const merge_toc_entry *key = (const merge_toc_entry *) p;
- hashval_t context_val = htab_hash_pointer (key->context);
- hashval_t name_val = htab_hash_string (key->name);
- hashval_t id_val = iterative_hash_hashval_t (name_val, TREE_CODE (key->expr));
- return iterative_hash_hashval_t (context_val, id_val);
-}
-
-static int
-htab_merge_key_eq (const void *p1, const void *p2)
-{
- const merge_toc_entry *key1 = (const merge_toc_entry *) p1;
- const merge_toc_entry *key2 = (const merge_toc_entry *) p2;
-
- if (key1->context != key2->context)
- return false;
-
- if (TREE_CODE (key1->expr) != TREE_CODE (key2->expr))
- return false;
-
- if (key1->name == NULL || key2->name == NULL)
- return false;
-
- return strcmp (key1->name, key2->name) == 0;
-}
-
-
-/* Look in TOC for an existing tree matching KEY. */
-
-static tree
-pph_toc_lookup (htab_t toc, merge_toc_entry *key)
-{
- void *slot = htab_find (toc, key);
- tree expr = NULL;
-
- if (slot)
- {
- merge_toc_entry *e = (merge_toc_entry *) slot;
- expr = e->expr;
- }
-
- return expr;
-}
-
-
-/* Insert KEY into TOC. */
-
-static void
-pph_toc_add (htab_t toc, merge_toc_entry *key)
-{
- void **slot;
- merge_toc_entry *entry;
-
- slot = htab_find_slot (toc, key, INSERT);
- gcc_assert (*slot == NULL);
-
- entry = XCNEW (merge_toc_entry);
- memcpy (entry, key, sizeof (*key));
- *slot = (void *) entry;
-}
-
-
-/* Prepend a tree EXPR to a CHAIN. */
-
-static tree
-pph_prepend_to_chain (tree expr, tree *chain)
-{
- DECL_CHAIN (expr) = *chain;
- *chain = expr;
- return expr;
-}
-
-
-/* Merge the just-read header for tree EXPR with NAME onto the CHAIN. */
-
-static tree
-pph_merge_into_chain (tree expr, const char *name, tree *chain)
-{
- merge_toc_entry key;
- tree found;
-
- key.expr = expr;
- key.context = chain;
- key.name = name;
- found = pph_toc_lookup (merge_toc, &key);
- if (!found)
- {
- pph_toc_add (merge_toc, &key);
-
- if (flag_pph_debug >= 3)
- fprintf (pph_logfile, "PPH: %s NOT found on chain\n", name);
-
- /* Types (as opposed to type decls) are not on a chain. */
- if (chain)
- return pph_prepend_to_chain (expr, chain);
- else
- return expr;
- }
-
- if (flag_pph_debug >= 3)
- fprintf (pph_logfile, "PPH: %s FOUND on chain\n", name);
-
- gcc_assert (TREE_CODE (found) == TREE_CODE (expr));
-
- return found;
-}
-
-
-/****************************************************************** bindings */
-
-
-/* Forward declaration to break cyclic dependencies. */
-static cp_binding_level *pph_in_binding_level (pph_stream *);
-
-/* Helper for pph_in_cxx_binding. Read and return a cxx_binding
- instance from STREAM. */
-
-static cxx_binding *
-pph_in_cxx_binding_1 (pph_stream *stream)
-{
- struct bitpack_d bp;
- cxx_binding *cb;
- tree value, type;
- enum pph_record_marker marker;
- unsigned ix, image_ix;
-
- marker = pph_in_start_record (stream, &image_ix, &ix, PPH_cxx_binding);
- if (marker == PPH_RECORD_END)
- return NULL;
- else if (pph_is_reference_marker (marker))
- return (cxx_binding *) pph_cache_find (stream, marker, image_ix, ix,
- PPH_cxx_binding);
-
- value = pph_in_tree (stream);
- type = pph_in_tree (stream);
- ALLOC_AND_REGISTER (&stream->cache, ix, PPH_cxx_binding, cb,
- cxx_binding_make (value, type));
- cb->scope = pph_in_binding_level (stream);
- bp = pph_in_bitpack (stream);
- cb->value_is_inherited = bp_unpack_value (&bp, 1);
- cb->is_local = bp_unpack_value (&bp, 1);
-
- return cb;
-}
-
-
-/* Read and return an instance of cxx_binding from STREAM. */
-
-static cxx_binding *
-pph_in_cxx_binding (pph_stream *stream)
-{
- cxx_binding *curr, *prev, *cb;
-
- /* Read the current binding first. */
- cb = pph_in_cxx_binding_1 (stream);
-
- /* Read the list of previous bindings. */
- for (curr = cb; curr; curr = prev)
- {
- prev = pph_in_cxx_binding_1 (stream);
- curr->previous = prev;
- }
-
- return cb;
-}
-
-
-/* Read all the fields of cp_class_binding instance CB to STREAM. */
-
-static cp_class_binding *
-pph_in_class_binding (pph_stream *stream)
-{
- cp_class_binding *cb;
- enum pph_record_marker marker;
- unsigned image_ix, ix;
-
- marker = pph_in_start_record (stream, &image_ix, &ix, PPH_cp_class_binding);
- if (marker == PPH_RECORD_END)
- return NULL;
- else if (pph_is_reference_marker (marker))
- return (cp_class_binding *) pph_cache_find (stream, marker, image_ix, ix,
- PPH_cp_class_binding);
-
- ALLOC_AND_REGISTER (&stream->cache, ix, PPH_cp_class_binding, cb,
- ggc_alloc_cleared_cp_class_binding ());
- cb->base = pph_in_cxx_binding (stream);
- cb->identifier = pph_in_tree (stream);
-
- return cb;
-}
-
-
-/* Read and return an instance of cp_label_binding from STREAM. */
-
-static cp_label_binding *
-pph_in_label_binding (pph_stream *stream)
-{
- cp_label_binding *lb;
- enum pph_record_marker marker;
- unsigned image_ix, ix;
-
- marker = pph_in_start_record (stream, &image_ix, &ix, PPH_cp_label_binding);
- if (marker == PPH_RECORD_END)
- return NULL;
- else if (pph_is_reference_marker (marker))
- return (cp_label_binding *) pph_cache_find (stream, marker, image_ix, ix,
- PPH_cp_label_binding);
-
- ALLOC_AND_REGISTER (&stream->cache, ix, PPH_cp_label_binding, lb,
- ggc_alloc_cleared_cp_label_binding ());
- lb->label = pph_in_tree (stream);
- lb->prev_value = pph_in_tree (stream);
-
- return lb;
-}
-
-
-/* Read the contents of binding level BL from STREAM. */
-
-static void
-pph_in_binding_level_1 (pph_stream *stream, cp_binding_level *bl)
-{
- unsigned i, num;
- struct bitpack_d bp;
-
- bl->this_entity = pph_in_tree (stream);
-
- num = pph_in_uint (stream);
- bl->class_shadowed = NULL;
- for (i = 0; i < num; i++)
- {
- cp_class_binding *cb = pph_in_class_binding (stream);
- VEC_safe_push (cp_class_binding, gc, bl->class_shadowed, cb);
- }
-
- bl->type_shadowed = pph_in_tree (stream);
-
- num = pph_in_uint (stream);
- bl->shadowed_labels = NULL;
- for (i = 0; i < num; i++)
- {
- cp_label_binding *sl = pph_in_label_binding (stream);
- VEC_safe_push (cp_label_binding, gc, bl->shadowed_labels, sl);
- }
-
- bl->blocks = pph_in_tree (stream);
- bl->level_chain = pph_in_binding_level (stream);
- bl->dead_vars_from_for = pph_in_tree_vec (stream);
- bl->statement_list = pph_in_chain (stream);
- bl->binding_depth = pph_in_uint (stream);
-
- bp = pph_in_bitpack (stream);
- bl->kind = (enum scope_kind) bp_unpack_value (&bp, 4);
- bl->keep = bp_unpack_value (&bp, 1);
- bl->more_cleanups_ok = bp_unpack_value (&bp, 1);
- bl->have_cleanups = bp_unpack_value (&bp, 1);
-}
-
-
-/* Read the start of a binding level. Return true when processing is done. */
-
-static bool
-pph_in_binding_level_start (pph_stream *stream, cp_binding_level **blp,
- unsigned *ixp)
-{
- unsigned image_ix;
- enum pph_record_marker marker;
-
- marker = pph_in_start_record (stream, &image_ix, ixp, PPH_cp_binding_level);
- if (marker == PPH_RECORD_END)
- {
- *blp = NULL;
- return true;
- }
- else if (pph_is_reference_marker (marker))
- {
- *blp = (cp_binding_level *)
- pph_cache_find (stream, marker, image_ix, *ixp, PPH_cp_binding_level);
- return true;
- }
- return false;
-}
-
-
-/* Read and return an instance of cp_binding_level from STREAM.
- This function is for use when we will not be merging the binding level. */
-
-static cp_binding_level *
-pph_in_binding_level (pph_stream *stream)
-{
- unsigned ix;
- cp_binding_level *bl;
-
- if (pph_in_binding_level_start (stream, &bl, &ix))
- return bl;
-
- bl = ggc_alloc_cleared_cp_binding_level ();
- pph_cache_insert_at (&stream->cache, bl, ix, PPH_cp_binding_level);
-
- bl->names = pph_in_chain (stream);
- bl->namespaces = pph_in_chain (stream);
- bl->usings = pph_in_chain (stream);
- bl->using_directives = pph_in_chain (stream);
- bl->static_decls = pph_in_tree_vec (stream);
- pph_in_binding_level_1 (stream, bl);
-
- return bl;
-}
-
-
-/* Read all the merge keys from STREAM into the cp_binding_level BL. */
-
-static void
-pph_in_binding_merge_keys (pph_stream *stream, cp_binding_level *bl)
-{
- /* Read all the merge keys and merge into the bindings. */
- pph_in_merge_key_chain (stream, &bl->names);
- pph_in_merge_key_chain (stream, &bl->namespaces);
- pph_in_merge_key_chain (stream, &bl->usings);
- pph_in_merge_key_chain (stream, &bl->using_directives);
-}
-
-
-/* Read all the merge bodies from STREAM into the cp_binding_level BL. */
-
-static void
-pph_in_binding_merge_bodies_1 (pph_stream *stream, cp_binding_level *bl)
-{
- pph_in_merge_body_chain (stream);
- pph_in_merge_body_chain (stream);
- pph_in_merge_body_chain (stream);
- pph_in_merge_body_chain (stream);
- pph_union_into_tree_vec (&bl->static_decls, pph_in_tree_vec (stream));
- /* FIXME pph: The following is probably too aggressive in overwriting. */
- pph_in_binding_level_1 (stream, bl);
-}
-
-
-/* Read all the merge bodies from STREAM into the cp_binding_level BL. */
-
-static void
-pph_in_binding_merge_bodies (pph_stream *stream, cp_binding_level *bl)
-{
- unsigned ix;
- cp_binding_level *new_bl;
-
- if (pph_in_binding_level_start (stream, &new_bl, &ix))
- {
- gcc_assert (new_bl == bl);
- return;
- }
-
- /* The binding level is already allocated. */
- pph_cache_insert_at (&stream->cache, bl, ix, PPH_cp_binding_level);
- pph_in_binding_merge_bodies_1 (stream, bl);
-}
-
-
-/********************************************************** tree aux classes */
-
-
-/* Read and return an instance of struct language_function from STREAM. */
-
-static struct language_function *
-pph_in_language_function (pph_stream *stream)
-{
- struct bitpack_d bp;
- struct language_function *lf;
- enum pph_record_marker marker;
- unsigned image_ix, ix;
-
- marker = pph_in_start_record (stream, &image_ix, &ix, PPH_language_function);
- if (marker == PPH_RECORD_END)
- return NULL;
- else if (pph_is_reference_marker (marker))
- return (struct language_function *) pph_cache_find (stream, marker,
- image_ix, ix,
- PPH_language_function);
-
- ALLOC_AND_REGISTER (&stream->cache, ix, PPH_language_function, lf,
- ggc_alloc_cleared_language_function ());
- lf->base.x_stmt_tree.x_cur_stmt_list = pph_in_tree_vec (stream);
- lf->base.x_stmt_tree.stmts_are_full_exprs_p = pph_in_uint (stream);
- lf->x_cdtor_label = pph_in_tree (stream);
- lf->x_current_class_ptr = pph_in_tree (stream);
- lf->x_current_class_ref = pph_in_tree (stream);
- lf->x_eh_spec_block = pph_in_tree (stream);
- lf->x_in_charge_parm = pph_in_tree (stream);
- lf->x_vtt_parm = pph_in_tree (stream);
- lf->x_return_value = pph_in_tree (stream);
- bp = pph_in_bitpack (stream);
- lf->returns_value = bp_unpack_value (&bp, 1);
- lf->returns_null = bp_unpack_value (&bp, 1);
- lf->returns_abnormally = bp_unpack_value (&bp, 1);
- lf->x_in_function_try_handler = bp_unpack_value (&bp, 1);
- lf->x_in_base_initializer = bp_unpack_value (&bp, 1);
- lf->can_throw = bp_unpack_value (&bp, 1);
-
- /* FIXME pph. We are not reading lf->x_named_labels. */
-
- lf->bindings = pph_in_binding_level (stream);
- lf->x_local_names = pph_in_tree_vec (stream);
-
- /* FIXME pph. We are not reading lf->extern_decl_map. */
-
- return lf;
-}
-
-
-/* Read applicable fields of struct function from STREAM. Associate
- the read structure to DECL. */
-
-static void
-pph_in_struct_function (pph_stream *stream, tree decl)
-{
- size_t count, i;
- unsigned image_ix, ix;
- enum pph_record_marker marker;
- struct function *fn;
- tree t;
-
- marker = pph_in_start_record (stream, &image_ix, &ix, PPH_function);
- if (marker == PPH_RECORD_END)
- return;
- else if (pph_is_reference_marker (marker))
- {
- fn = (struct function *) pph_cache_find (stream, marker, image_ix, ix,
- PPH_function);
- gcc_assert (DECL_STRUCT_FUNCTION (decl) == fn);
- return;
- }
-
- /* Possibly allocate a new DECL_STRUCT_FUNCTION for DECL. */
- t = pph_in_tree (stream);
- gcc_assert (t == decl);
- fn = DECL_STRUCT_FUNCTION (decl);
- if (!fn)
- {
- /* The DECL_STRUCT_FUNCTION does not already already exists,
- which implies that we are reading an entirely new function
- and not merging into an existing function. */
- /* We would normally use ALLOC_AND_REGISTER,
- but allocate_struct_function does not return a pointer. */
- allocate_struct_function (decl, false);
- fn = DECL_STRUCT_FUNCTION (decl);
- }
-
- /* Now register it. */
- pph_cache_insert_at (&stream->cache, fn, ix, PPH_function);
-
- /* FIXME pph: For now, accept the new version of the fields when merging. */
-
- input_struct_function_base (fn, stream->encoder.r.data_in,
- stream->encoder.r.ib);
-
- /* struct eh_status *eh; -- zero init */
- /* struct control_flow_graph *cfg; -- zero init */
- /* struct gimple_seq_d *gimple_body; -- zero init */
- /* struct gimple_df *gimple_df; -- zero init */
- /* struct loops *x_current_loops; -- zero init */
- /* struct stack_usage *su; -- zero init */
- /* htab_t value_histograms; -- zero init */
- /* tree decl; -- zero init */
- /* tree static_chain_decl; -- in base */
- /* tree nonlocal_goto_save_area; -- in base */
- /* tree local_decls; -- in base */
- /* struct machine_function * machine; -- zero init */
-
- fn->language = pph_in_language_function (stream);
-
- count = pph_in_uint (stream);
- if ( count > 0 )
- {
- fn->used_types_hash = htab_create_ggc (37, htab_hash_pointer,
- htab_eq_pointer, NULL);
- for (i = 0; i < count; i++)
- {
- void **slot;
- tree type = pph_in_tree (stream);
- slot = htab_find_slot (fn->used_types_hash, type, INSERT);
- if (*slot == NULL)
- *slot = type;
- }
- }
- /* else zero initialized */
-
- /* int last_stmt_uid; -- zero init */
- /* int funcdef_no; -- zero init */
- /* location_t function_start_locus; -- in base */
- /* location_t function_end_locus; -- in base */
- /* unsigned int curr_properties; -- in base */
- /* unsigned int last_verified; -- zero init */
- /* const char *cannot_be_copied_reason; -- zero init */
-
- /* unsigned int va_list_gpr_size : 8; -- in base */
- /* unsigned int va_list_fpr_size : 8; -- in base */
- /* unsigned int calls_setjmp : 1; -- in base */
- /* unsigned int calls_alloca : 1; -- in base */
- /* unsigned int has_nonlocal_label : 1; -- in base */
- /* unsigned int cannot_be_copied_set : 1; -- zero init */
- /* unsigned int stdarg : 1; -- in base */
- /* unsigned int after_inlining : 1; -- in base */
- /* unsigned int always_inline_functions_inlined : 1; -- in base */
- /* unsigned int can_throw_non_call_exceptions : 1; -- in base */
- /* unsigned int returns_struct : 1; -- in base */
- /* unsigned int returns_pcc_struct : 1; -- in base */
- /* unsigned int after_tree_profile : 1; -- in base */
- /* unsigned int has_local_explicit_reg_vars : 1; -- in base */
- /* unsigned int is_thunk : 1; -- in base */
-}
-
-
-/* Read all fields in lang_decl_base instance LDB from STREAM. */
-
-static void
-pph_in_ld_base (pph_stream *stream, struct lang_decl_base *ldb)
-{
- struct bitpack_d bp;
-
- bp = pph_in_bitpack (stream);
- ldb->selector = bp_unpack_value (&bp, 16);
- ldb->language = (enum languages) bp_unpack_value (&bp, 4);
- ldb->use_template = bp_unpack_value (&bp, 2);
- ldb->not_really_extern = bp_unpack_value (&bp, 1);
- ldb->initialized_in_class = bp_unpack_value (&bp, 1);
- ldb->repo_available_p = bp_unpack_value (&bp, 1);
- ldb->threadprivate_or_deleted_p = bp_unpack_value (&bp, 1);
- ldb->anticipated_p = bp_unpack_value (&bp, 1);
- ldb->friend_attr = bp_unpack_value (&bp, 1);
- ldb->template_conv_p = bp_unpack_value (&bp, 1);
- ldb->odr_used = bp_unpack_value (&bp, 1);
- ldb->u2sel = bp_unpack_value (&bp, 1);
-}
-
-
-/* Read all the fields in lang_decl_min instance LDM from STREAM. */
-
-static void
-pph_in_ld_min (pph_stream *stream, struct lang_decl_min *ldm)
-{
- ldm->template_info = pph_in_tree (stream);
- if (ldm->base.u2sel == 0)
- ldm->u2.access = pph_in_tree (stream);
- else if (ldm->base.u2sel == 1)
- ldm->u2.discriminator = pph_in_uint (stream);
- else
- gcc_unreachable ();
-}
-
-
-/* Read all the fields of lang_decl_fn instance LDF from STREAM. */
-
-static void
-pph_in_ld_fn (pph_stream *stream, struct lang_decl_fn *ldf)
-{
- struct bitpack_d bp;
-
- /* Read all the fields in lang_decl_min. */
- pph_in_ld_min (stream, &ldf->min);
-
- bp = pph_in_bitpack (stream);
- ldf->operator_code = (enum tree_code) bp_unpack_value (&bp, 16);
- ldf->global_ctor_p = bp_unpack_value (&bp, 1);
- ldf->global_dtor_p = bp_unpack_value (&bp, 1);
- ldf->constructor_attr = bp_unpack_value (&bp, 1);
- ldf->destructor_attr = bp_unpack_value (&bp, 1);
- ldf->assignment_operator_p = bp_unpack_value (&bp, 1);
- ldf->static_function = bp_unpack_value (&bp, 1);
- ldf->pure_virtual = bp_unpack_value (&bp, 1);
- ldf->defaulted_p = bp_unpack_value (&bp, 1);
- ldf->has_in_charge_parm_p = bp_unpack_value (&bp, 1);
- ldf->has_vtt_parm_p = bp_unpack_value (&bp, 1);
- ldf->pending_inline_p = bp_unpack_value (&bp, 1);
- ldf->nonconverting = bp_unpack_value (&bp, 1);
- ldf->thunk_p = bp_unpack_value (&bp, 1);
- ldf->this_thunk_p = bp_unpack_value (&bp, 1);
- ldf->hidden_friend_p = bp_unpack_value (&bp, 1);
-
- ldf->befriending_classes = pph_in_tree (stream);
- ldf->context = pph_in_tree (stream);
-
- if (ldf->thunk_p == 0)
- ldf->u5.cloned_function = pph_in_tree (stream);
- else if (ldf->thunk_p == 1)
- ldf->u5.fixed_offset = pph_in_uint (stream);
- else
- gcc_unreachable ();
-
- if (ldf->pending_inline_p == 1)
- ldf->u.pending_inline_info = pph_in_token_cache (stream);
- else if (ldf->pending_inline_p == 0)
- ldf->u.saved_language_function = pph_in_language_function (stream);
-}
-
-
-/* Read all the fields of lang_decl_ns instance LDNS from STREAM. */
-
-static void
-pph_in_ld_ns (pph_stream *stream, struct lang_decl_ns *ldns)
-{
- if (ldns->level == NULL)
- ldns->level = pph_in_binding_level (stream);
- else
- pph_in_binding_merge_bodies (stream, ldns->level);
-}
-
-
-/* Read all the fields of lang_decl_parm instance LDP from STREAM. */
-
-static void
-pph_in_ld_parm (pph_stream *stream, struct lang_decl_parm *ldp)
-{
- ldp->level = pph_in_uint (stream);
- ldp->index = pph_in_uint (stream);
-}
-
-
-/* Read language specific data in DECL from STREAM. */
-
-static void
-pph_in_lang_specific (pph_stream *stream, tree decl)
-{
- struct lang_decl *ld;
- struct lang_decl_base *ldb;
- enum pph_record_marker marker;
- unsigned image_ix, ix;
-
- marker = pph_in_start_record (stream, &image_ix, &ix, PPH_lang_decl);
- if (marker == PPH_RECORD_END)
- return;
- else if (pph_is_reference_marker (marker))
- {
- DECL_LANG_SPECIFIC (decl) =
- (struct lang_decl *) pph_cache_find (stream, marker, image_ix, ix,
- PPH_lang_decl);
- return;
- }
-
- /* Allocate a lang_decl structure for DECL, if not already present.
- Namespace merge keys preallocate it. */
- ld = DECL_LANG_SPECIFIC (decl);
- if (!ld)
- {
- retrofit_lang_decl (decl);
- ld = DECL_LANG_SPECIFIC (decl);
- }
-
- /* Now register it. We would normally use ALLOC_AND_REGISTER,
- but retrofit_lang_decl does not return a pointer. */
- pph_cache_insert_at (&stream->cache, ld, ix, PPH_lang_decl);
-
- /* Read all the fields in lang_decl_base. */
- ldb = &ld->u.base;
- pph_in_ld_base (stream, ldb);
-
- if (ldb->selector == 0)
- {
- /* Read all the fields in lang_decl_min. */
- pph_in_ld_min (stream, &ld->u.min);
- }
- else if (ldb->selector == 1)
- {
- /* Read all the fields in lang_decl_fn. */
- pph_in_ld_fn (stream, &ld->u.fn);
- }
- else if (ldb->selector == 2)
- {
- /* Read all the fields in lang_decl_ns. */
- pph_in_ld_ns (stream, &ld->u.ns);
- }
- else if (ldb->selector == 3)
- {
- /* Read all the fields in lang_decl_parm. */
- pph_in_ld_parm (stream, &ld->u.parm);
- }
- else
- gcc_unreachable ();
-}
-
-
-/********************************************************* tree base classes */
-
-
-/* Read in the tree_common fields. */
-
-static void
-pph_in_tree_common (pph_stream *stream, tree t)
-{
- /* The 'struct tree_typed typed' base class is handled in LTO. */
- TREE_CHAIN (t) = pph_in_tree (stream);
-}
-
-
-/* Read all the fields in lang_type_header instance LTH from STREAM. */
-
-static void
-pph_in_lang_type_header (pph_stream *stream, struct lang_type_header *lth)
-{
- struct bitpack_d bp;
-
- bp = pph_in_bitpack (stream);
- lth->is_lang_type_class = bp_unpack_value (&bp, 1);
- lth->has_type_conversion = bp_unpack_value (&bp, 1);
- lth->has_copy_ctor = bp_unpack_value (&bp, 1);
- lth->has_default_ctor = bp_unpack_value (&bp, 1);
- lth->const_needs_init = bp_unpack_value (&bp, 1);
- lth->ref_needs_init = bp_unpack_value (&bp, 1);
- lth->has_const_copy_assign = bp_unpack_value (&bp, 1);
-}
-
-
-/* Read a struct sorted_fields_type instance SFT to STREAM. */
-
-static struct sorted_fields_type *
-pph_in_sorted_fields_type (pph_stream *stream)
-{
- unsigned i, num_fields;
- struct sorted_fields_type *v;
- enum pph_record_marker marker;
- unsigned image_ix, ix;
-
- marker = pph_in_start_record (stream, &image_ix, &ix, PPH_sorted_fields_type);
- if (marker == PPH_RECORD_END)
- return NULL;
- else if (pph_is_reference_marker (marker))
- return (struct sorted_fields_type *)
- pph_cache_find (stream, marker, image_ix, ix, PPH_sorted_fields_type);
-
- num_fields = pph_in_uint (stream);
- ALLOC_AND_REGISTER (&stream->cache, ix, PPH_sorted_fields_type, v,
- sorted_fields_type_new (num_fields));
- for (i = 0; i < num_fields; i++)
- v->elts[i] = pph_in_tree (stream);
-
- return v;
-}
-
-
-/* Read all the fields in lang_type_class instance LTC to STREAM. */
-
-static void
-pph_in_lang_type_class (pph_stream *stream, struct lang_type_class *ltc)
-{
- struct bitpack_d bp;
- enum pph_record_marker marker;
- unsigned image_ix, ix;
-
- ltc->align = pph_in_uchar (stream);
-
- bp = pph_in_bitpack (stream);
- ltc->has_mutable = bp_unpack_value (&bp, 1);
- ltc->com_interface = bp_unpack_value (&bp, 1);
- ltc->non_pod_class = bp_unpack_value (&bp, 1);
- ltc->nearly_empty_p = bp_unpack_value (&bp, 1);
- ltc->user_align = bp_unpack_value (&bp, 1);
- ltc->has_copy_assign = bp_unpack_value (&bp, 1);
- ltc->has_new = bp_unpack_value (&bp, 1);
- ltc->has_array_new = bp_unpack_value (&bp, 1);
- ltc->gets_delete = bp_unpack_value (&bp, 2);
- ltc->interface_only = bp_unpack_value (&bp, 1);
- ltc->interface_unknown = bp_unpack_value (&bp, 1);
- ltc->contains_empty_class_p = bp_unpack_value (&bp, 1);
- ltc->anon_aggr = bp_unpack_value (&bp, 1);
- ltc->non_zero_init = bp_unpack_value (&bp, 1);
- ltc->empty_p = bp_unpack_value (&bp, 1);
- ltc->vec_new_uses_cookie = bp_unpack_value (&bp, 1);
- ltc->declared_class = bp_unpack_value (&bp, 1);
- ltc->diamond_shaped = bp_unpack_value (&bp, 1);
- ltc->repeated_base = bp_unpack_value (&bp, 1);
- ltc->being_defined = bp_unpack_value (&bp, 1);
- ltc->java_interface = bp_unpack_value (&bp, 1);
- ltc->debug_requested = bp_unpack_value (&bp, 1);
- ltc->fields_readonly = bp_unpack_value (&bp, 1);
- ltc->use_template = bp_unpack_value (&bp, 2);
- ltc->ptrmemfunc_flag = bp_unpack_value (&bp, 1);
- ltc->was_anonymous = bp_unpack_value (&bp, 1);
- ltc->lazy_default_ctor = bp_unpack_value (&bp, 1);
- ltc->lazy_copy_ctor = bp_unpack_value (&bp, 1);
- ltc->lazy_copy_assign = bp_unpack_value (&bp, 1);
- ltc->lazy_destructor = bp_unpack_value (&bp, 1);
- ltc->has_const_copy_ctor = bp_unpack_value (&bp, 1);
- ltc->has_complex_copy_ctor = bp_unpack_value (&bp, 1);
- ltc->has_complex_copy_assign = bp_unpack_value (&bp, 1);
- ltc->non_aggregate = bp_unpack_value (&bp, 1);
- ltc->has_complex_dflt = bp_unpack_value (&bp, 1);
- ltc->has_list_ctor = bp_unpack_value (&bp, 1);
- ltc->non_std_layout = bp_unpack_value (&bp, 1);
- ltc->is_literal = bp_unpack_value (&bp, 1);
- ltc->lazy_move_ctor = bp_unpack_value (&bp, 1);
- ltc->lazy_move_assign = bp_unpack_value (&bp, 1);
- ltc->has_complex_move_ctor = bp_unpack_value (&bp, 1);
- ltc->has_complex_move_assign = bp_unpack_value (&bp, 1);
- ltc->has_constexpr_ctor = bp_unpack_value (&bp, 1);
-
- ltc->primary_base = pph_in_tree (stream);
- ltc->vcall_indices = pph_in_tree_pair_vec (stream);
- ltc->vtables = pph_in_tree (stream);
- ltc->typeinfo_var = pph_in_tree (stream);
- ltc->vbases = pph_in_tree_vec (stream);
-
- marker = pph_in_start_record (stream, &image_ix, &ix, PPH_binding_table);
- if (marker == PPH_RECORD_START)
- {
- ltc->nested_udts = pph_in_binding_table (stream);
- pph_cache_insert_at (&stream->cache, ltc->nested_udts, ix,
- PPH_binding_table);
- }
- else if (pph_is_reference_marker (marker))
- ltc->nested_udts = (binding_table) pph_cache_find (stream, marker,
- image_ix, ix,
- PPH_binding_table);
-
- ltc->as_base = pph_in_tree (stream);
- ltc->pure_virtuals = pph_in_tree_vec (stream);
- ltc->friend_classes = pph_in_tree (stream);
- ltc->methods = pph_in_tree_vec (stream);
- ltc->key_method = pph_in_tree (stream);
- ltc->decl_list = pph_in_tree (stream);
- ltc->template_info = pph_in_tree (stream);
- ltc->befriending_classes = pph_in_tree (stream);
- ltc->objc_info = pph_in_tree (stream);
- ltc->sorted_fields = pph_in_sorted_fields_type (stream);
- ltc->lambda_expr = pph_in_tree (stream);
-}
-
-
-/* Read all fields of struct lang_type_ptrmem instance LTP from STREAM. */
-
-static void
-pph_in_lang_type_ptrmem (pph_stream *stream,
- struct lang_type_ptrmem *ltp)
-{
- ltp->record = pph_in_tree (stream);
-}
-
-
-/* Read all the fields in struct lang_type from STREAM. */
-
-static struct lang_type *
-pph_in_lang_type (pph_stream *stream)
-{
- struct lang_type *lt;
- enum pph_record_marker marker;
- unsigned image_ix, ix;
-
- marker = pph_in_start_record (stream, &image_ix, &ix, PPH_lang_type);
- if (marker == PPH_RECORD_END)
- return NULL;
- else if (pph_is_reference_marker (marker))
- return (struct lang_type *) pph_cache_find (stream, marker, image_ix, ix,
- PPH_lang_type);
-
- ALLOC_AND_REGISTER (&stream->cache, ix, PPH_lang_type, lt,
- ggc_alloc_cleared_lang_type (sizeof (struct lang_type)));
-
- pph_in_lang_type_header (stream, <->u.h);
- if (lt->u.h.is_lang_type_class)
- pph_in_lang_type_class (stream, <->u.c);
- else
- pph_in_lang_type_ptrmem (stream, <->u.ptrmem);
-
- return lt;
-}
-
-
-/* Read from STREAM the body of tcc_type node TYPE. */
-
-static void
-pph_in_tcc_type (pph_stream *stream, tree type)
-{
- TYPE_LANG_SPECIFIC (type) = pph_in_lang_type (stream);
- TYPE_POINTER_TO (type) = pph_in_tree (stream);
- TYPE_REFERENCE_TO (type) = pph_in_tree (stream);
- TYPE_NEXT_VARIANT (type) = pph_in_tree (stream);
- /* FIXME pph - Streaming TYPE_CANONICAL generates many type comparison
- failures. Why? */
- /* FIXME pph: apparently redundant. */
- TREE_CHAIN (type) = pph_in_tree (stream);
-
- /* The type values cache is built as constants are instantiated,
- so we only stream it on the nodes that use it for
- other purposes. */
- switch (TREE_CODE (type))
- {
- case BOUND_TEMPLATE_TEMPLATE_PARM:
- case DECLTYPE_TYPE:
- case TEMPLATE_TEMPLATE_PARM:
- case TEMPLATE_TYPE_PARM:
- case TYPENAME_TYPE:
- case TYPEOF_TYPE:
- TYPE_VALUES_RAW (type) = pph_in_tree (stream);
- break;
-
- default:
- break;
- }
-
- /* If TYPE has a METHOD_VEC, we need to resort it. Name lookup in
- classes relies on the specific ordering of the class method
- pointers. Since we generally instantiate them in a different
- order than the original compile, the pointer values will be
- different. This will cause name lookups to fail, unless we
- resort the vector. */
- if (CLASS_TYPE_P (type) && CLASSTYPE_METHOD_VEC (type))
- finish_struct_methods (type);
-}
-
-
-/* Read from STREAM the body of tcc_declaration tree DECL. */
-
-static void
-pph_in_tcc_declaration (pph_stream *stream, tree decl)
-{
- pph_in_lang_specific (stream, decl);
- DECL_INITIAL (decl) = pph_in_tree (stream);
-
- /* The tree streamer only writes DECL_CHAIN for PARM_DECL nodes.
- We need to read DECL_CHAIN for variables and functions because
- they are sometimes chained together in places other than regular
- tree chains. For example in BINFO_VTABLEs, the decls are chained
- together). */
- if (TREE_CODE (decl) == VAR_DECL
- || TREE_CODE (decl) == FUNCTION_DECL)
- DECL_CHAIN (decl) = pph_in_tree (stream);
-
- /* Handle some individual decl nodes. */
- switch (TREE_CODE (decl))
- {
- case FUNCTION_DECL:
- DECL_SAVED_TREE (decl) = pph_in_tree (stream);
- break;
-
- case TYPE_DECL:
- DECL_ORIGINAL_TYPE (decl) = pph_in_tree (stream);
- break;
-
- case TEMPLATE_DECL:
- DECL_TEMPLATE_RESULT (decl) = pph_in_tree (stream);
- DECL_TEMPLATE_PARMS (decl) = pph_in_tree (stream);
- break;
-
- default:
- break;
- }
-
- /* When the declaration was compiled originally, the parser marks
- it DECL_EXTERNAL, to avoid emitting it more than once. It also
- remembers the true external state in DECL_NOT_REALLY_EXTERN. So,
- if both bits are set, the declaration should not be considered
- external. */
- if (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_LANG_SPECIFIC (decl)
- && DECL_NOT_REALLY_EXTERN (decl)
- && DECL_EXTERNAL (decl))
- {
- DECL_EXTERNAL (decl) = 0;
- DECL_NOT_REALLY_EXTERN (decl) = 0;
- }
-}
-
-
-/******************************************************** tree head and body */
-
-
-/* Read the body fields of EXPR from STREAM. */
-
-static void
-pph_in_tree_body (pph_stream *stream, tree expr)
-{
- struct lto_input_block *ib = stream->encoder.r.ib;
- struct data_in *data_in = stream->encoder.r.data_in;
- bool handled_p;
-
- /* Read the language-independent parts of EXPR's body. */
- streamer_read_tree_body (ib, data_in, expr);
-
- /* Handle common tree code classes first. */
- handled_p = true;
- switch (TREE_CODE_CLASS (TREE_CODE (expr)))
- {
- case tcc_declaration:
- pph_in_tcc_declaration (stream, expr);
- break;
-
- case tcc_type:
- pph_in_tcc_type (stream, expr);
- break;
-
- case tcc_constant:
- if (TREE_CODE (expr) == PTRMEM_CST)
- {
- pph_in_tree_common (stream, expr);
- PTRMEM_CST_MEMBER (expr) = pph_in_tree (stream);
- }
- break;
-
- case tcc_expression:
- case tcc_unary:
- case tcc_binary:
- case tcc_vl_exp:
- case tcc_reference:
- case tcc_comparison:
- case tcc_statement:
- /* These tree classes are completely handled by the tree streamer. */
- break;
-
- default:
- handled_p = false;
- break;
- }
-
- /* If we've already handled the tree, we are done. */
- if (handled_p)
- return;
-
- /* Only tcc_exceptional tree codes are left to handle. */
- gcc_assert (TREE_CODE_CLASS (TREE_CODE (expr)) == tcc_exceptional);
-
- switch (TREE_CODE (expr))
- {
- case STATEMENT_LIST:
- {
- HOST_WIDE_INT i, num_trees = pph_in_uint (stream);
- for (i = 0; i < num_trees; i++)
- {
- tree stmt = pph_in_tree (stream);
- append_to_statement_list_force (stmt, &expr);
- }
- }
- break;
-
- case OVERLOAD:
- pph_in_tree_common (stream, expr);
- OVL_FUNCTION (expr) = pph_in_tree (stream);
- break;
-
- case IDENTIFIER_NODE:
- if (flag_pph_debug >= 3)
- fprintf (pph_logfile, "in identifier %s\n", IDENTIFIER_POINTER (expr));
- IDENTIFIER_NAMESPACE_BINDINGS (expr) = pph_in_cxx_binding (stream);
- IDENTIFIER_BINDING (expr) = pph_in_cxx_binding (stream);
- IDENTIFIER_TEMPLATE (expr) = pph_in_tree (stream);
- IDENTIFIER_LABEL_VALUE (expr) = pph_in_tree (stream);
- REAL_IDENTIFIER_TYPE_VALUE (expr) = pph_in_tree (stream);
- break;
-
- case BASELINK:
- pph_in_tree_common (stream, expr);
- BASELINK_BINFO (expr) = pph_in_tree (stream);
- BASELINK_FUNCTIONS (expr) = pph_in_tree (stream);
- BASELINK_ACCESS_BINFO (expr) = pph_in_tree (stream);
- break;
-
- case TEMPLATE_INFO:
- pph_in_tree_common (stream, expr);
- TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (expr)
- = pph_in_qual_use_vec (stream);
- break;
-
- case DEFAULT_ARG:
- pph_in_tree_common (stream, expr);
- DEFARG_TOKENS (expr) = pph_in_token_cache (stream);
- DEFARG_INSTANTIATIONS (expr) = pph_in_tree_vec (stream);
- break;
-
- case STATIC_ASSERT:
- pph_in_tree_common (stream, expr);
- STATIC_ASSERT_CONDITION (expr) = pph_in_tree (stream);
- STATIC_ASSERT_MESSAGE (expr) = pph_in_tree (stream);
- STATIC_ASSERT_SOURCE_LOCATION (expr) = pph_in_location (stream);
- break;
-
- case ARGUMENT_PACK_SELECT:
- pph_in_tree_common (stream, expr);
- ARGUMENT_PACK_SELECT_FROM_PACK (expr) = pph_in_tree (stream);
- ARGUMENT_PACK_SELECT_INDEX (expr) = pph_in_uint (stream);
- break;
-
- case TRAIT_EXPR:
- pph_in_tree_common (stream, expr);
- TRAIT_EXPR_TYPE1 (expr) = pph_in_tree (stream);
- TRAIT_EXPR_TYPE2 (expr) = pph_in_tree (stream);
- TRAIT_EXPR_KIND (expr) = (enum cp_trait_kind) pph_in_uint (stream);
- break;
-
- case LAMBDA_EXPR:
- pph_in_tree_common (stream, expr);
- LAMBDA_EXPR_LOCATION (expr) = pph_in_location (stream);
- LAMBDA_EXPR_CAPTURE_LIST (expr) = pph_in_tree (stream);
- LAMBDA_EXPR_THIS_CAPTURE (expr) = pph_in_tree (stream);
- LAMBDA_EXPR_RETURN_TYPE (expr) = pph_in_tree (stream);
- LAMBDA_EXPR_EXTRA_SCOPE (expr) = pph_in_tree (stream);
- LAMBDA_EXPR_DISCRIMINATOR (expr) = pph_in_uint (stream);
- break;
-
- case TREE_VEC:
- /* TREE_VECs hold template argument lists. */
- NON_DEFAULT_TEMPLATE_ARGS_COUNT (expr) = pph_in_tree (stream);
- break;
-
- case PLACEHOLDER_EXPR:
- TREE_TYPE (expr) = pph_in_tree (stream);
- break;
-
- case TEMPLATE_PARM_INDEX:
- pph_in_tree_common (stream, expr);
- TEMPLATE_PARM_IDX (expr) = pph_in_uint (stream);
- TEMPLATE_PARM_LEVEL (expr) = pph_in_uint (stream);
- TEMPLATE_PARM_ORIG_LEVEL (expr) = pph_in_uint (stream);
- TEMPLATE_PARM_NUM_SIBLINGS (expr) = pph_in_uint (stream);
- TEMPLATE_PARM_DECL (expr) = pph_in_tree (stream);
- break;
-
- case DEFERRED_NOEXCEPT:
- DEFERRED_NOEXCEPT_PATTERN (expr) = pph_in_tree (stream);
- DEFERRED_NOEXCEPT_ARGS (expr) = pph_in_tree (stream);
- break;
-
- /* TREES ALREADY HANDLED */
- case ERROR_MARK:
- case TREE_LIST:
- case BLOCK:
- case CONSTRUCTOR:
- case SSA_NAME:
- case TREE_BINFO:
- break;
-
- /* TREES UNIMPLEMENTED */
- case OMP_CLAUSE:
- case OPTIMIZATION_NODE:
- case TARGET_OPTION_NODE:
- fatal_error ("PPH: unimplemented tree node '%s'",
- pph_tree_code_text (TREE_CODE (expr)));
- break;
-
- /* TREES UNRECOGNIZED */
- default:
- fatal_error ("PPH: unrecognized tree node '%s'",
- pph_tree_code_text (TREE_CODE (expr)));
- }
-}
-
-
-/* Unpack language-dependent bitfields from BP into EXPR. */
-
-static void
-pph_unpack_value_fields (struct bitpack_d *bp, tree expr)
-{
- if (TYPE_P (expr))
- {
- TYPE_LANG_FLAG_0 (expr) = bp_unpack_value (bp, 1);
- TYPE_LANG_FLAG_1 (expr) = bp_unpack_value (bp, 1);
- TYPE_LANG_FLAG_2 (expr) = bp_unpack_value (bp, 1);
- TYPE_LANG_FLAG_3 (expr) = bp_unpack_value (bp, 1);
- TYPE_LANG_FLAG_4 (expr) = bp_unpack_value (bp, 1);
- TYPE_LANG_FLAG_5 (expr) = bp_unpack_value (bp, 1);
- TYPE_LANG_FLAG_6 (expr) = bp_unpack_value (bp, 1);
- }
- else if (DECL_P (expr))
- {
- DECL_LANG_FLAG_0 (expr) = bp_unpack_value (bp, 1);
- DECL_LANG_FLAG_1 (expr) = bp_unpack_value (bp, 1);
- DECL_LANG_FLAG_2 (expr) = bp_unpack_value (bp, 1);
- DECL_LANG_FLAG_3 (expr) = bp_unpack_value (bp, 1);
- DECL_LANG_FLAG_4 (expr) = bp_unpack_value (bp, 1);
- DECL_LANG_FLAG_5 (expr) = bp_unpack_value (bp, 1);
- DECL_LANG_FLAG_6 (expr) = bp_unpack_value (bp, 1);
- DECL_LANG_FLAG_7 (expr) = bp_unpack_value (bp, 1);
- DECL_LANG_FLAG_8 (expr) = bp_unpack_value (bp, 1);
- }
-
- TREE_LANG_FLAG_0 (expr) = bp_unpack_value (bp, 1);
- TREE_LANG_FLAG_1 (expr) = bp_unpack_value (bp, 1);
- TREE_LANG_FLAG_2 (expr) = bp_unpack_value (bp, 1);
- TREE_LANG_FLAG_3 (expr) = bp_unpack_value (bp, 1);
- TREE_LANG_FLAG_4 (expr) = bp_unpack_value (bp, 1);
- TREE_LANG_FLAG_5 (expr) = bp_unpack_value (bp, 1);
- TREE_LANG_FLAG_6 (expr) = bp_unpack_value (bp, 1);
-}
-
-
-/* Read a tree header from STREAM and allocate a memory instance for it.
- Return the new tree. */
-
-static tree
-pph_in_tree_header (pph_stream *stream, enum LTO_tags tag)
-{
- struct lto_input_block *ib = stream->encoder.r.ib;
- struct data_in *data_in = stream->encoder.r.data_in;
- struct bitpack_d bp;
- tree expr;
- enum tree_code code;
-
- /* Allocate the tree. Handle C++-specific codes first. */
- code = lto_tag_to_tree_code (tag);
- if (code == AGGR_INIT_EXPR)
- {
- unsigned nargs = pph_in_uint (stream);
- expr = build_vl_exp (AGGR_INIT_EXPR, nargs + 3);
- }
- else
- expr = streamer_alloc_tree (ib, data_in, tag);
-
- /* Read the language-independent bitfields for EXPR. */
- bp = streamer_read_tree_bitfields (ib, expr);
-
- /* Unpack all language-dependent bitfields. */
- pph_unpack_value_fields (&bp, expr);
-
- return expr;
-}
-
-
-/* Read a merge key from STREAM. If the merge key read from STREAM
- is not found in *CHAIN, the newly allocated tree is added to it. */
-
-static tree
-pph_in_merge_key_tree (pph_stream *stream, tree *chain)
-{
- struct lto_input_block *ib = stream->encoder.r.ib;
- enum pph_record_marker marker;
- unsigned image_ix, ix;
- tree read_expr, expr;
- enum LTO_tags tag;
- const char *name;
-
- marker = pph_in_start_record (stream, &image_ix, &ix, PPH_any_tree);
- if (marker == PPH_RECORD_END)
- return NULL;
- else if (pph_is_reference_marker (marker))
- return (tree) pph_cache_find (stream, marker, image_ix, ix, PPH_any_tree);
- gcc_assert (marker == PPH_RECORD_START_MERGE_KEY);
-
- tag = streamer_read_record_start (ib);
-
- /* Materialize a new node from STREAM. This will also read all the
- language-independent bitfields for the new tree. */
- read_expr = pph_in_tree_header (stream, tag);
- gcc_assert (pph_tree_is_mergeable (read_expr));
- name = pph_in_string (stream);
-
- /* Look for a match in CHAIN to READ_EXPR's header. If we found a
- match, EXPR will be the existing tree that matches READ_EXPR.
- Otherwise, EXPR is the newly allocated READ_EXPR. */
- expr = pph_merge_into_chain (read_expr, name, chain);
-
- gcc_assert (expr != NULL);
-
- pph_cache_insert_at (&stream->cache, expr, ix, pph_tree_code_to_tag (expr));
-
- if (flag_pph_tracer)
- pph_trace_tree (expr, pph_trace_front,
- expr == read_expr ? pph_trace_unmerged_key
- : pph_trace_merged_key);
-
- if (DECL_P (expr))
- {
- if (TREE_CODE (expr) == NAMESPACE_DECL)
- {
- cp_binding_level *bl;
- if (DECL_LANG_SPECIFIC (expr))
- /* Merging into an existing namespace. */
- bl = NAMESPACE_LEVEL (expr);
- else
- {
- /* This is a new namespace. */
- retrofit_lang_decl (expr);
- bl = ggc_alloc_cleared_cp_binding_level ();
- NAMESPACE_LEVEL (expr) = bl;
- }
- pph_in_binding_merge_keys (stream, bl);
- }
-#if 0
-/* FIXME pph: Disable type merging for the moment. */
- else if (TREE_CODE (expr) == TYPE_DECL)
- /* Types are not on a chain. */
- TREE_TYPE (expr) = pph_in_merge_key_tree (stream, NULL);
- }
- else if (CLASS_TYPE_P (expr))
- {
- pph_in_merge_key_chain (stream, &TYPE_FIELDS (expr));
- pph_in_merge_key_chain (stream, &TYPE_METHODS (expr));
- /*FIXME pph: Nested types are broken.
- pph_in_binding_table (stream, &CLASSTYPE_NESTED_UTDS (expr));
- pph_in_merge_key_chain (stream, &CLASSTYPE_DECL_LIST (expr));
- */
-#endif
- }
-
- if (flag_pph_tracer)
- pph_trace_tree (expr, pph_trace_back,
- expr == read_expr ? pph_trace_unmerged_key
- : pph_trace_merged_key);
-
- return expr;
-}
-
-
-/* Read and return a tree from STREAM. */
-
-tree
-pph_in_tree (pph_stream *stream)
-{
- struct lto_input_block *ib = stream->encoder.r.ib;
- struct data_in *data_in = stream->encoder.r.data_in;
- tree expr = NULL;
- enum pph_record_marker marker;
- unsigned image_ix, ix;
- enum LTO_tags tag;
- tree saved_expr_chain = NULL;
-
- /* Read record start and test cache. */
- marker = pph_in_start_record (stream, &image_ix, &ix, PPH_any_tree);
- if (marker == PPH_RECORD_END)
- return NULL;
- else if (pph_is_reference_marker (marker))
- return (tree) pph_cache_find (stream, marker, image_ix, ix, PPH_any_tree);
- else if (marker == PPH_RECORD_START || marker == PPH_RECORD_START_NO_CACHE)
- {
- /* This is a new tree that we need to allocate. Start by
- reading the header fields, so we know how to allocate it
- (different tree nodes need to be allocated in different
- ways). */
- tag = streamer_read_record_start (ib);
- gcc_assert ((unsigned) tag < (unsigned) LTO_NUM_TAGS);
- if (tag == LTO_builtin_decl)
- {
- /* If we are going to read a built-in function, all we need is
- the code and class. */
- gcc_assert (marker == PPH_RECORD_START_NO_CACHE);
- return streamer_get_builtin_tree (ib, data_in);
- }
- else if (tag == lto_tree_code_to_tag (INTEGER_CST))
- {
- /* For integer constants we only need the type and its hi/low
- words. */
- gcc_assert (marker == PPH_RECORD_START_NO_CACHE);
- return streamer_read_integer_cst (ib, data_in);
- }
-
- /* Materialize a new node from STREAM. This will also read all the
- language-independent bitfields for the new tree. */
- expr = pph_in_tree_header (stream, tag);
- }
-
- gcc_assert (marker == PPH_RECORD_START
- || marker == PPH_RECORD_START_MUTATED
- || marker == PPH_RECORD_START_MERGE_BODY);
-
- if (marker == PPH_RECORD_START_MUTATED)
- {
- /* When reading a mutated tree, we only need to re-read its
- body, the tree itself is already in the cache for another
- PPH image. */
- expr = (tree) pph_cache_find (stream, PPH_RECORD_XREF, image_ix, ix,
- PPH_any_tree);
-
- /* Read the internal cache slot where EXPR should be stored at. */
- ix = pph_in_uint (stream);
- }
- else if (marker == PPH_RECORD_START_MERGE_BODY)
- {
- /* When reading a merge body, the tree has already been allocated
- and added to STREAM's cache. All we have to do now is read
- its body. FIXME pph, this read should be a merging read; we are
- overwriting EXPR's fields now. */
- expr = (tree) pph_cache_get (&stream->cache, ix);
- }
-
- /* Add the new tree to the cache and read its body. The tree is
- added to the cache before we read its body to handle circular
- references and references from children nodes. If we are reading
- a merge body, then the tree is already in the cache (it was added
- by pph_in_merge_key_tree). */
- if (marker != PPH_RECORD_START_MERGE_BODY)
- pph_cache_insert_at (&stream->cache, expr, ix, pph_tree_code_to_tag (expr));
-
- if (flag_pph_tracer)
- pph_trace_tree (expr, pph_trace_front,
- marker == PPH_RECORD_START_MERGE_BODY ? pph_trace_merge_body
- : marker == PPH_RECORD_START_MUTATED ? pph_trace_mutate
- : pph_trace_normal );
-
- /* If we are reading a merge body, it means that EXPR is already in
- some chain. Given that EXPR may now be in a different location
- in the chain, we need to make sure we do not lose it. */
- if (marker == PPH_RECORD_START_MERGE_BODY)
- saved_expr_chain = TREE_CHAIN (expr);
-
- pph_in_tree_body (stream, expr);
-
- /* Restore TREE_CHAIN if necessary. FIXME pph, we should just not
- save TREE_CHAIN for merge bodies. */
- if (marker == PPH_RECORD_START_MERGE_BODY)
- TREE_CHAIN (expr) = saved_expr_chain;
-
- if (flag_pph_tracer)
- pph_trace_tree (expr, pph_trace_back,
- marker == PPH_RECORD_START_MERGE_BODY ? pph_trace_merge_body
- : marker == PPH_RECORD_START_MUTATED ? pph_trace_mutate
- : pph_trace_normal );
-
- /* If needed, sign the recently materialized tree to detect
- mutations. Note that we only need to compute signatures
- if we are generating a PPH image. That is the only time
- where we need to determine whether a tree read from PPH
- was updated while parsing the header file that we are
- currently generating. */
- if (pph_writer_enabled_p () && tree_needs_signature (expr))
- {
- unsigned crc;
- size_t nbytes;
- crc = pph_get_signature (expr, &nbytes);
- pph_cache_sign (&stream->cache, ix, crc, nbytes);
- }
-
- return expr;
-}
-
-
-/************************************************************* file contents */
-
-
-/* Read a symbol table marker from STREAM. */
-
-static inline enum pph_symtab_action
-pph_in_symtab_action (pph_stream *stream)
-{
- enum pph_symtab_action m = (enum pph_symtab_action) pph_in_uchar (stream);
- gcc_assert (m == PPH_SYMTAB_DECLARE || m == PPH_SYMTAB_EXPAND);
- return m;
-}
-
-
-/* Read and return a callgraph node from STREAM. If this is the first
- time we read this node, add it to the callgraph. */
-
-static struct cgraph_node *
-pph_in_cgraph_node (pph_stream *stream)
-{
- enum pph_record_marker marker;
- unsigned image_ix, ix;
- struct cgraph_node *node;
- tree fndecl;
- struct bitpack_d bp;
-
- marker = pph_in_start_record (stream, &image_ix, &ix, PPH_cgraph_node);
- if (marker == PPH_RECORD_END)
- return NULL;
- else if (pph_is_reference_marker (marker))
- return (struct cgraph_node *) pph_cache_find (stream, marker, image_ix,
- ix, PPH_cgraph_node);
-
- fndecl = pph_in_tree (stream);
- ALLOC_AND_REGISTER (&stream->cache, ix, PPH_cgraph_node, node,
- cgraph_get_create_node (fndecl));
-
- node->origin = pph_in_cgraph_node (stream);
- node->nested = pph_in_cgraph_node (stream);
- node->next_nested = pph_in_cgraph_node (stream);
- node->next_needed = pph_in_cgraph_node (stream);
- node->next_sibling_clone = pph_in_cgraph_node (stream);
- node->prev_sibling_clone = pph_in_cgraph_node (stream);
- node->clones = pph_in_cgraph_node (stream);
- node->clone_of = pph_in_cgraph_node (stream);
- node->same_comdat_group = pph_in_cgraph_node (stream);
- gcc_assert (node->call_site_hash == NULL);
- node->former_clone_of = pph_in_tree (stream);
- gcc_assert (node->aux == NULL);
- gcc_assert (VEC_empty (ipa_opt_pass, node->ipa_transforms_to_apply));
-
- gcc_assert (VEC_empty (ipa_ref_t, node->ref_list.references));
- gcc_assert (VEC_empty (ipa_ref_ptr, node->ref_list.refering));
-
- gcc_assert (node->local.lto_file_data == NULL);
- bp = pph_in_bitpack (stream);
- node->local.local = bp_unpack_value (&bp, 1);
- node->local.externally_visible = bp_unpack_value (&bp, 1);
- node->local.finalized = bp_unpack_value (&bp, 1);
- node->local.can_change_signature = bp_unpack_value (&bp, 1);
- node->local.redefined_extern_inline = bp_unpack_value (&bp, 1);
-
- node->global.inlined_to = pph_in_cgraph_node (stream);
-
- node->rtl.preferred_incoming_stack_boundary = pph_in_uint (stream);
-
- gcc_assert (VEC_empty (ipa_replace_map_p, node->clone.tree_map));
- node->thunk.fixed_offset = pph_in_uhwi (stream);
- node->thunk.virtual_value = pph_in_uhwi (stream);
- node->thunk.alias = pph_in_tree (stream);
- bp = pph_in_bitpack (stream);
- node->thunk.this_adjusting = bp_unpack_value (&bp, 1);
- node->thunk.virtual_offset_p = bp_unpack_value (&bp, 1);
- node->thunk.thunk_p = bp_unpack_value (&bp, 1);
-
- node->count = pph_in_uhwi (stream);
- node->count_materialization_scale = pph_in_uint (stream);
-
- bp = pph_in_bitpack (stream);
- node->needed = bp_unpack_value (&bp, 1);
- node->address_taken = bp_unpack_value (&bp, 1);
- node->abstract_and_needed = bp_unpack_value (&bp, 1);
- node->reachable = bp_unpack_value (&bp, 1);
- node->reachable_from_other_partition = bp_unpack_value (&bp, 1);
- node->lowered = bp_unpack_value (&bp, 1);
- node->analyzed = bp_unpack_value (&bp, 1);
- node->in_other_partition = bp_unpack_value (&bp, 1);
- node->process = bp_unpack_value (&bp, 1);
- node->alias = bp_unpack_value (&bp, 1);
- node->same_body_alias = bp_unpack_value (&bp, 1);
- node->frequency = (enum node_frequency) bp_unpack_value (&bp, 2);
- node->only_called_at_startup = bp_unpack_value (&bp, 1);
- node->only_called_at_exit = bp_unpack_value (&bp, 1);
-
- return node;
-}
-
-
-/* Have we already emitted this DECL? */
-
-static bool
-pph_decl_already_emitted (tree decl)
-{
- static struct pointer_set_t *emitted_syms = NULL;
- gcc_assert (decl != NULL);
- if (!emitted_syms)
- emitted_syms = pointer_set_create ();
- return pointer_set_insert (emitted_syms, decl) != 0;
-}
-
-
-/* Have we already emitted this cgraph NODE? */
-
-static bool
-pph_node_already_emitted (struct cgraph_node *node)
-{
- static struct pointer_set_t *emitted_nodes = NULL;
- gcc_assert (node != NULL);
- if (!emitted_nodes)
- emitted_nodes = pointer_set_create ();
- return pointer_set_insert (emitted_nodes, node) != 0;
-}
-
-
-/* Read the symbol table from STREAM. When this image is read into
- another translation unit, we want to guarantee that the IL
- instances taken from this image are instantiated in the same order
- that they were instantiated when we generated this image.
-
- With this, we can generate code in the same order out of the
- original header files and out of PPH images. */
-
-static void
-pph_in_symtab (pph_stream *stream)
-{
- unsigned i, num;
-
- /* Register all the symbols in STREAM in the same order of the
- original compilation for this header file. */
- num = pph_in_uint (stream);
- for (i = 0; i < num; i++)
- {
- enum pph_symtab_action action;
- tree decl;
- bool top_level, at_end;
-
- action = pph_in_symtab_action (stream);
- decl = pph_in_tree (stream);
- if (action == PPH_SYMTAB_DECLARE)
- {
- struct bitpack_d bp;
- bp = pph_in_bitpack (stream);
- top_level = bp_unpack_value (&bp, 1);
- at_end = bp_unpack_value (&bp, 1);
- if (pph_decl_already_emitted (decl))
- continue;
-
- cp_rest_of_decl_compilation (decl, top_level, at_end);
- }
- else if (action == PPH_SYMTAB_EXPAND)
- {
- struct cgraph_node *node;
-
- pph_in_struct_function (stream, decl);
- node = pph_in_cgraph_node (stream);
- if (node && node->local.finalized)
- {
- if (pph_node_already_emitted (node))
- continue;
-
- /* Since the writer had finalized this cgraph node,
- we have to re-play its actions. To do that, we need
- to clear the finalized and reachable bits in the
- node, otherwise cgraph_finalize_function will toss
- out this node. */
- node->local.finalized = false;
- node->reachable = false;
- cgraph_finalize_function (node->decl, true);
- }
- }
- else
- gcc_unreachable ();
- }
-}
-
-
-/* Wrap a macro DEFINITION for printing in an error. */
-
-static char *
-wrap_macro_def (const char *definition)
-{
- char *string;
- if (definition)
- {
- size_t length;
- length = strlen (definition);
- string = (char *) xmalloc (length+3);
- string[0] = '"';
- strcpy (string + 1, definition);
- string[length + 1] = '"';
- string[length + 2] = '\0';
- }
- else
- string = xstrdup ("undefined");
- return string;
-}
-
-
-/* Report a macro validation error in FILENAME for macro IDENT,
- which should have the value EXPECTED but actually had the value FOUND. */
-
-static void
-report_validation_error (const char *filename,
- const char *ident, const char *found,
- const char *before, const char *after)
-{
- char* quote_found = wrap_macro_def (found);
- char* quote_before = wrap_macro_def (before);
- char* quote_after = wrap_macro_def (after);
- warning (0, "PPH file %s fails macro validation, "
- "%s is %s and should be %s or %s\n",
- filename, ident, quote_found, quote_before, quote_after);
- free (quote_found);
- free (quote_before);
- free (quote_after);
-}
-
-
-/* Load the IDENTIFIERS for a hunk from a STREAM. */
-
-static void
-pph_in_identifiers (pph_stream *stream, cpp_idents_used *identifiers)
-{
- unsigned int j;
- unsigned int max_ident_len, max_value_len, num_entries;
- unsigned int ident_len, before_len, after_len;
-
- max_ident_len = pph_in_uint (stream);
- identifiers->max_ident_len = max_ident_len;
- max_value_len = pph_in_uint (stream);
- identifiers->max_value_len = max_value_len;
- num_entries = pph_in_uint (stream);
- identifiers->num_entries = num_entries;
- identifiers->entries = XCNEWVEC (cpp_ident_use, num_entries);
- identifiers->strings = XCNEW (struct obstack);
-
- /* Strings need no alignment. */
- _obstack_begin (identifiers->strings, 0, 0,
- (void *(*) (long)) xmalloc,
- (void (*) (void *)) free);
- obstack_alignment_mask (identifiers->strings) = 0;
- /* FIXME pph: We probably need to free all these things somewhere. */
-
- /* Read the identifiers in HUNK. */
- for (j = 0; j < num_entries; ++j)
- {
- const char *s;
- identifiers->entries[j].used_by_directive = pph_in_uint (stream);
- identifiers->entries[j].expanded_to_text = pph_in_uint (stream);
- s = pph_in_string (stream);
- gcc_assert (s);
- ident_len = strlen (s);
- identifiers->entries[j].ident_len = ident_len;
- identifiers->entries[j].ident_str =
- (const char *) obstack_copy0 (identifiers->strings, s, ident_len);
-
- s = pph_in_string (stream);
- if (s)
- {
- before_len = strlen (s);
- identifiers->entries[j].before_len = before_len;
- identifiers->entries[j].before_str = (const char *)
- obstack_copy0 (identifiers->strings, s, before_len);
- }
- else
- {
- /* The identifier table expects NULL entries to have
- a length of -1U. */
- identifiers->entries[j].before_len = -1U;
- identifiers->entries[j].before_str = NULL;
- }
-
- s = pph_in_string (stream);
- if (s)
- {
- after_len = strlen (s);
- identifiers->entries[j].after_len = after_len;
- identifiers->entries[j].after_str = (const char *)
- obstack_copy0 (identifiers->strings, s, after_len);
- }
- else
- {
- /* The identifier table expects NULL entries to have
- a length of -1U. */
- identifiers->entries[j].after_len = -1U;
- identifiers->entries[j].after_str = NULL;
- }
- }
-}
-
-
-/* Read global bindings from STREAM into scope_chain->bindings. Note
- that this does not call pph_in_binding_level because that would
- overwrite the fields merged by pph_in_merge_keys. */
-
-static void
-pph_in_global_binding (pph_stream *stream)
-{
- unsigned image_ix, ix;
- enum pph_record_marker marker;
- cp_binding_level *bl;
-
- bl = scope_chain->bindings;
- marker = pph_in_start_record (stream, &image_ix, &ix, PPH_cp_binding_level);
- gcc_assert (marker != PPH_RECORD_END);
-
- if (pph_is_reference_marker (marker))
- {
- /* If we found a reference to BL, it should be the same. This happens
- when we pull BL from a nested PPH image. */
- cp_binding_level *other_bl;
- other_bl = (cp_binding_level *) pph_cache_find (stream, marker, image_ix,
- ix, PPH_cp_binding_level);
- gcc_assert (other_bl == bl);
- }
- else
- {
- /* Note that here we do not allocate a new binding level. Since we
- are reading into the global one, we register the current
- scope_chain->bindings into the cache. Otherwise, we would be
- associating these symbols into the global binding level from
- STREAM, instead of the current translation unit. */
- pph_cache_insert_at (&stream->cache, bl, ix, PPH_cp_binding_level);
- }
-
- /* Read the merge keys and merge them into the current compilation
- context. Since we have registered scope_chain->bindings in the
- same slot IX that the writer used, the trees read now will be
- bound to scope_chain->bindings. */
- pph_in_binding_merge_keys (stream, bl);
- pph_in_binding_merge_bodies_1 (stream, bl);
-}
-
-
-/* Helper for pph_read_file. Read contents of PPH file in STREAM. */
-
-static void
-pph_read_file_1 (pph_stream *stream)
-{
- bool verified;
- cpp_ident_use *bad_use;
- const char *cur_def;
- cpp_idents_used idents_used;
- tree t, file_keyed_classes, file_static_aggregates;
- unsigned i;
- VEC(tree,gc) *file_unemitted_tinfo_decls;
- source_location cpp_token_replay_loc;
-
- /* If we have read STREAM before, we do not need to re-read the rest
- of its body. We only needed to read its line table. */
- if (stream->in_memory_p)
- return;
-
- if (flag_pph_tracer >= 1)
- fprintf (pph_logfile, "PPH: Reading %s\n", stream->name);
-
- /* Read in STREAM's line table and merge it in the current line table.
- At the same time, read in includes in the order they were originally
- read. */
- cpp_token_replay_loc = pph_in_line_table_and_includes (stream);
-
- /* Read all the identifiers and pre-processor symbols in the global
- namespace. */
- pph_in_identifiers (stream, &idents_used);
-
- /* FIXME pph: This validation is weak. */
- verified = cpp_lt_verify_1 (parse_in, &idents_used, &bad_use, &cur_def, true);
- if (!verified)
- report_validation_error (stream->name, bad_use->ident_str, cur_def,
- bad_use->before_str, bad_use->after_str);
-
- /* Re-instantiate all the pre-processor symbols defined by STREAM. Force
- their source_location to line 1 / column 0 of the file they were included
- in. This avoids shifting all of the line_table's locations as we would by
- adding locations which wouldn't be there in the non-pph compile; thus
- working towards an identical line_table in pph and non-pph. */
- cpp_lt_replay (parse_in, &idents_used, &cpp_token_replay_loc);
-
- /* Read the bindings from STREAM. */
- pph_in_global_binding (stream);
-
- /* Read and merge the other global state collected during parsing of
- the original header. */
- file_keyed_classes = pph_in_tree (stream);
- keyed_classes = chainon (file_keyed_classes, keyed_classes);
-
- file_unemitted_tinfo_decls = pph_in_tree_vec (stream);
- FOR_EACH_VEC_ELT (tree, file_unemitted_tinfo_decls, i, t)
- VEC_safe_push (tree, gc, unemitted_tinfo_decls, t);
-
- pph_in_pending_templates_list (stream);
- pph_in_spec_entry_tables (stream);
-
- file_static_aggregates = pph_in_tree (stream);
- static_aggregates = chainon (file_static_aggregates, static_aggregates);
-
- /* Read and process the symbol table. */
- pph_in_symtab (stream);
-
- /* Mark this file as read. If other images need to access its contents,
- we will not need to actually read it again. */
- pph_mark_stream_read (stream);
-
- if (flag_pph_dump_tree)
- pph_dump_namespace (pph_logfile, global_namespace);
-}
-
-
-/* Read PPH file FILENAME. Return the in-memory pph_stream instance. */
-
-pph_stream *
-pph_read_file (const char *filename)
-{
- pph_stream *stream = pph_stream_open (filename, "rb");
- if (stream == NULL)
- fatal_error ("cannot open PPH file %s for reading: %m", filename);
-
- pph_read_file_1 (stream);
-
- return stream;
-}
-
-
-/********************************************************* stream operations */
-
-
-/* Initialize the reader. */
-
-void
-pph_reader_init (void)
-{
- merge_toc = htab_create (551, htab_merge_key_hash, htab_merge_key_eq, free);
-}
-
-
-/* Finalize the reader. */
-
-void
-pph_reader_finish (void)
-{
- htab_delete (merge_toc);
-}
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c (revision 181815)
+++ gcc/cp/pt.c (working copy)
@@ -46,7 +46,6 @@ along with GCC; see the file COPYING3.
#include "timevar.h"
#include "tree-iterator.h"
#include "vecprim.h"
-#include "pph-streamer.h"
/* The type of functions taking a tree, and some additional data, and
returning an int. */
Index: gcc/cp/pph-streamer.c
===================================================================
--- gcc/cp/pph-streamer.c (revision 181815)
+++ gcc/cp/pph-streamer.c (working copy)
@@ -1,674 +0,0 @@
-/* Routines for streaming PPH data.
- Copyright (C) 2011 Free Software Foundation, Inc.
- Contributed by Diego Novillo <dnovillo@google.com>.
-
- This file is part of GCC.
-
- GCC 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 3, or (at your option)
- any later version.
-
- GCC 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 GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "pph.h"
-#include "tree.h"
-#include "langhooks.h"
-#include "tree-iterator.h"
-#include "tree-pretty-print.h"
-#include "lto-streamer.h"
-#include "pph-streamer.h"
-#include "tree-pass.h"
-#include "version.h"
-#include "cppbuiltin.h"
-#include "streamer-hooks.h"
-
-/* List of PPH images opened for reading. Images opened during #include
- processing and opened from pph_in_includes cannot be closed
- immediately after reading, because the pickle cache contained in
- them may be referenced from other images. We delay closing all of
- them until the end of parsing (when pph_streamer_finish is called). */
-static VEC(pph_stream_ptr, heap) *pph_read_images = NULL;
-
-/* A cache of pre-loaded common tree nodes. */
-static pph_cache *pph_preloaded_cache;
-
-/* Pre-load common tree nodes into CACHE. These nodes are always built by the
- front end, so there is no need to pickle them. */
-
-static void
-pph_cache_preload (pph_cache *cache)
-{
- unsigned i;
-
- for (i = itk_char; i < itk_none; i++)
- pph_cache_add (cache, integer_types[i], NULL,
- pph_tree_code_to_tag (integer_types[i]));
-
- for (i = 0; i < TYPE_KIND_LAST; i++)
- pph_cache_add (cache, sizetype_tab[i], NULL,
- pph_tree_code_to_tag (sizetype_tab[i]));
-
- /* global_trees[] can have NULL entries in it. Skip them. */
- for (i = 0; i < TI_MAX; i++)
- if (global_trees[i])
- pph_cache_add (cache, global_trees[i], NULL,
- pph_tree_code_to_tag (global_trees[i]));
-
- /* c_global_trees[] can have NULL entries in it. Skip them. */
- for (i = 0; i < CTI_MAX; i++)
- if (c_global_trees[i])
- pph_cache_add (cache, c_global_trees[i], NULL,
- pph_tree_code_to_tag (c_global_trees[i]));
-
- /* cp_global_trees[] can have NULL entries in it. Skip them. */
- for (i = 0; i < CPTI_MAX; i++)
- {
- /* Also skip trees which are generated while parsing. */
- if (i == CPTI_KEYED_CLASSES)
- continue;
-
- if (cp_global_trees[i])
- pph_cache_add (cache, cp_global_trees[i], NULL,
- pph_tree_code_to_tag (cp_global_trees[i]));
- }
-
- /* Add other well-known nodes that should always be taken from the
- current compilation context. */
- pph_cache_add (cache, global_namespace, NULL,
- pph_tree_code_to_tag (global_namespace));
- pph_cache_add (cache, DECL_CONTEXT (global_namespace), NULL,
- pph_tree_code_to_tag (DECL_CONTEXT (global_namespace)));
-}
-
-
-/* Callback for writing ASTs to a stream. Write EXPR to the PPH stream
- in OB. */
-
-static void
-pph_write_tree (struct output_block *ob, tree expr, bool ref_p ATTRIBUTE_UNUSED)
-{
- pph_out_tree ((pph_stream *) ob->sdata, expr);
-}
-
-
-/* Callback for reading ASTs from a stream. Instantiate and return a
- new tree from the PPH stream in DATA_IN. */
-
-static tree
-pph_read_tree (struct lto_input_block *ib ATTRIBUTE_UNUSED,
- struct data_in *data_in)
-{
- return pph_in_tree ((pph_stream *) data_in->sdata);
-}
-
-
-/* Callback for streamer_hooks.input_location. An offset is applied to
- the location_t read in according to the properties of the merged
- line_table. IB and DATA_IN are as in lto_input_location. This function
- should only be called after pph_in_and_merge_line_table was called as
- we expect pph_loc_offset to be set. */
-
-static location_t
-pph_input_location (struct lto_input_block *ib ATTRIBUTE_UNUSED,
- struct data_in *data_in)
-{
- return pph_in_location ((pph_stream *) data_in->sdata);
-}
-
-
-/* Callback for streamer_hooks.output_location. Output the LOC directly,
- an offset will be applied on input after rebuilding the line_table.
- OB and LOC are as in lto_output_location. */
-
-static void
-pph_output_location (struct output_block *ob, location_t loc)
-{
- pph_out_location ((pph_stream *) ob->sdata, loc);
-}
-
-
-/* Initialize all the streamer hooks used for streaming ASTs. */
-
-static void
-pph_hooks_init (void)
-{
- streamer_hooks_init ();
- streamer_hooks.write_tree = pph_write_tree;
- streamer_hooks.read_tree = pph_read_tree;
- streamer_hooks.input_location = pph_input_location;
- streamer_hooks.output_location = pph_output_location;
-}
-
-
-/* Initialize an empty pickle CACHE. */
-
-static void
-pph_cache_init (pph_cache *cache)
-{
- cache->v = NULL;
- cache->m = pointer_map_create ();
-}
-
-
-/* Initialize the pre-loaded cache. This contains all the common
- tree nodes built by the compiler on startup. */
-
-static void
-pph_init_preloaded_cache (void)
-{
- pph_preloaded_cache = XCNEW (pph_cache);
- pph_cache_init (pph_preloaded_cache);
- pph_cache_preload (pph_preloaded_cache);
-}
-
-
-/* Initialize the streamer. */
-
-void
-pph_streamer_init (void)
-{
- pph_hooks_init ();
- pph_init_preloaded_cache ();
-}
-
-
-/* Finalize the streamer. */
-
-void
-pph_streamer_finish (void)
-{
- unsigned i;
- pph_stream *image;
-
- /* Finalize the writer. */
- pph_writer_finish ();
-
- /* Finalize the reader. */
- pph_reader_finish ();
-
- /* Close any images read during parsing. */
- FOR_EACH_VEC_ELT (pph_stream_ptr, pph_read_images, i, image)
- pph_stream_close (image);
-
- VEC_free (pph_stream_ptr, heap, pph_read_images);
-}
-
-
-/* If FILENAME has already been read, return the stream associated with it. */
-
-static pph_stream *
-pph_find_stream_for (const char *filename)
-{
- pph_stream *include;
- unsigned i;
-
- /* FIXME pph, implement a hash map to avoid this linear search. */
- FOR_EACH_VEC_ELT (pph_stream_ptr, pph_read_images, i, include)
- if (strcmp (include->name, filename) == 0)
- return include;
-
- return NULL;
-}
-
-
-/* Add STREAM to the list of read images. */
-
-void
-pph_mark_stream_read (pph_stream *stream)
-{
- stream->in_memory_p = true;
- VEC_safe_push (pph_stream_ptr, heap, pph_read_images, stream);
-}
-
-
-/* Create a new PPH stream to be stored on the file called NAME.
- MODE is passed to fopen directly. */
-
-pph_stream *
-pph_stream_open (const char *name, const char *mode)
-{
- pph_stream *stream;
- FILE *f;
-
- /* If we have already opened a PPH stream named NAME, just return
- its associated stream. */
- stream = pph_find_stream_for (name);
- if (stream)
- {
- gcc_assert (stream->in_memory_p);
- return stream;
- }
-
- f = fopen (name, mode);
- if (!f)
- return NULL;
-
- stream = XCNEW (pph_stream);
- stream->file = f;
- stream->name = xstrdup (name);
- stream->write_p = (strchr (mode, 'w') != NULL);
- pph_cache_init (&stream->cache);
- stream->preloaded_cache = pph_preloaded_cache;
- if (stream->write_p)
- pph_init_write (stream);
- else
- pph_init_read (stream);
-
- return stream;
-}
-
-
-
-/* Close PPH stream STREAM. */
-
-void
-pph_stream_close (pph_stream *stream)
-{
- /* STREAM can be NULL if it could not be properly opened. An error
- has already been emitted, so avoid crashing here. */
- if (stream == NULL)
- return;
-
- if (flag_pph_tracer >= 1)
- fprintf (pph_logfile, "PPH: Closing %s\n", stream->name);
-
- /* If we were writing to STREAM, flush all the memory buffers. This
- does the actual writing of all the pickled data structures. */
- if (stream->write_p)
- pph_flush_buffers (stream);
-
- fclose (stream->file);
-
- /* Deallocate all memory used. */
- stream->file = NULL;
- VEC_free (pph_cache_entry, heap, stream->cache.v);
- pointer_map_destroy (stream->cache.m);
- VEC_free (pph_symtab_entry, heap, stream->symtab.v);
- VEC_free (pph_stream_ptr, heap, stream->includes);
-
- if (stream->write_p)
- {
- destroy_output_block (stream->encoder.w.ob);
- free (stream->encoder.w.decl_state_stream);
- lto_delete_out_decl_state (stream->encoder.w.out_state);
- }
- else
- {
- unsigned i;
-
- free (stream->encoder.r.ib);
- lto_data_in_delete (stream->encoder.r.data_in);
- for (i = 0; i < PPH_NUM_SECTIONS; i++)
- free (stream->encoder.r.pph_sections[i]);
- free (stream->encoder.r.pph_sections);
- free (stream->encoder.r.file_data);
- }
-
- free (stream);
-}
-
-
-/* Add INCLUDE, and the images included by it, to the list of files
- included by STREAM. */
-
-void
-pph_add_include (pph_stream *stream, pph_stream *include)
-{
- pph_stream *include_child;
- unsigned i;
-
- include->parent = stream;
- VEC_safe_push (pph_stream_ptr, heap, stream->includes, include);
- FOR_EACH_VEC_ELT (pph_stream_ptr, include->includes, i, include_child)
- VEC_safe_push (pph_stream_ptr, heap, stream->includes, include_child);
-}
-
-
-/* Trace a record MARKER and TAG. */
-
-static const char *marker_strings[] =
-{
- "PPH_RECORD_START",
- "PPH_RECORD_START_NO_CACHE",
- "PPH_RECORD_START_MUTATED",
- "PPH_RECORD_START_MERGE_KEY",
- "PPH_RECORD_START_MERGE_BODY",
- "PPH_RECORD_END",
- "PPH_RECORD_IREF",
- "PPH_RECORD_XREF",
- "PPH_RECORD_PREF"
-};
-
-static const char *tag_strings[] =
-{
- "PPH_any_tree",
- "PPH_binding_entry",
- "PPH_binding_table",
- "PPH_cgraph_node",
- "PPH_cp_binding_level",
- "PPH_cp_class_binding",
- "PPH_cp_label_binding",
- "PPH_cxx_binding",
- "PPH_function",
- "PPH_lang_decl",
- "PPH_lang_type",
- "PPH_language_function",
- "PPH_sorted_fields_type"
-};
-
-void
-pph_trace_marker (enum pph_record_marker marker, enum pph_tag tag)
-{
- fprintf (pph_logfile, "marker ");
- if (PPH_RECORD_START <= marker && marker <= PPH_RECORD_PREF)
- fprintf (pph_logfile, "%s", marker_strings[marker - PPH_RECORD_START]);
- else
- fprintf (pph_logfile, "unknown");
- fprintf (pph_logfile, " tag ");
- if (tag == PPH_null)
- fprintf (pph_logfile, "PPH_null\n");
- else if (tag < PPH_any_tree)
- fprintf (pph_logfile, "%s\n", tree_code_name[tag]);
- else if (tag < PPH_NUM_TAGS)
- fprintf (pph_logfile, "%s\n", tag_strings[tag - PPH_any_tree]);
- else
- fprintf (pph_logfile, "unknown\n");
-}
-
-
-/* Print tracing information for a possibly MERGEABLE tree T. */
-
-void
-pph_trace_tree (tree t, enum pph_trace_end end, enum pph_trace_kind kind)
-{
- char end_char, kind_char, decl_char;
- bool is_merge, is_decl;
- bool emit = false;
-
- switch (kind)
- {
- case pph_trace_key_out:
- kind_char = 'K';
- is_merge = true;
- break;
- case pph_trace_unmerged_key:
- kind_char = 'U';
- is_merge = true;
- break;
- case pph_trace_merged_key:
- kind_char = 'M';
- is_merge = true;
- break;
- case pph_trace_merge_body:
- kind_char = 'B';
- is_merge = true;
- break;
- case pph_trace_mutate:
- kind_char = '=';
- is_merge = false;
- break;
- case pph_trace_normal:
- kind_char = '.';
- is_merge = false;
- break;
- default:
- kind_char = '?';
- is_merge = false;
- }
-
- end_char = end == pph_trace_front ? '{' : '}';
-
- is_decl = DECL_P (t);
- if (is_decl)
- decl_char = 'D';
- else if (TYPE_P (t))
- decl_char = 'T';
- else
- decl_char = '.';
-
- if (is_merge && is_decl && flag_pph_tracer >= 2)
- emit = true;
- else if ((is_merge || is_decl) && flag_pph_tracer >= 3)
- emit = true;
- else if (!EXPR_P (t) && flag_pph_tracer >= 4)
- emit = true;
-
- if (emit)
- {
- fprintf (pph_logfile, "PPH: %c%c%c ", end_char, kind_char, decl_char);
- if (kind == pph_trace_unmerged_key || end == pph_trace_front)
- fprintf (pph_logfile, "%s -------\n",
- pph_tree_code_text (TREE_CODE (t)));
- else
- pph_dump_tree_name (pph_logfile, t, 0);
- }
-}
-
-
-/* Insert DATA in CACHE at slot IX. TAG represents the data structure
- pointed-to by DATA. As a restriction to prevent stomping on cache
- entries, this will not allow inserting into the same slot more than
- once. Return the newly added entry. */
-
-pph_cache_entry *
-pph_cache_insert_at (pph_cache *cache, void *data, unsigned ix,
- enum pph_tag tag)
-{
- void **map_slot;
- pph_cache_entry e = { data, tag, false, 0, 0 };
-
- map_slot = pointer_map_insert (cache->m, data);
-
- /* We should not be trying to insert the same data more than once.
- This indicates that the same DATA pointer has been given two
- different cache locations. This almost always points to a
- problem with merging data structures read from different files. */
- gcc_assert (*map_slot == NULL);
-
- *map_slot = (void *) (intptr_t) ix;
- if (ix + 1 > VEC_length (pph_cache_entry, cache->v))
- VEC_safe_grow_cleared (pph_cache_entry, heap, cache->v, ix + 1);
- VEC_replace (pph_cache_entry, cache->v, ix, &e);
-
- return pph_cache_get_entry (cache, ix);
-}
-
-
-/* If DATA exists in CACHE, return the cache entry holding it. If
- IX_P is not NULL, store the cache slot where DATA resides in *IX_P
- (or (unsigned)-1 if DATA is not found). If CACHE is NULL use
- pph_preloaded_cache.
-
- If a cache hit is found, the data type tag for the entry must match
- TAG. */
-
-pph_cache_entry *
-pph_cache_lookup (pph_cache *cache, void *data, unsigned *ix_p,
- enum pph_tag tag)
-{
- void **map_slot;
- unsigned ix;
- pph_cache_entry *e;
-
- if (cache == NULL)
- cache = pph_preloaded_cache;
-
- map_slot = pointer_map_contains (cache->m, data);
- if (map_slot == NULL)
- {
- e = NULL;
- ix = (unsigned) -1;
- }
- else
- {
- intptr_t slot_ix = (intptr_t) *map_slot;
- gcc_assert (slot_ix == (intptr_t)(unsigned) slot_ix);
- ix = (unsigned) slot_ix;
- e = pph_cache_get_entry (cache, ix);
-
- /* If the caller is looking for a specific TAG, make sure
- it matches the tag we pulled from the cache. */
- if (tag != PPH_null)
- gcc_assert (tag == e->tag);
- }
-
- if (ix_p)
- *ix_p = ix;
-
- return e;
-}
-
-
-/* Return true if DATA is in the pickle cache of one of STREAM's
- included images. TAG is the expected data type TAG for data.
-
- If DATA is found:
- - the index for INCLUDE_P into IMAGE->INCLUDES is returned in
- *INCLUDE_IX_P (if INCLUDE_IX_P is not NULL),
- - the cache slot index for DATA into *INCLUDE_P's pickle cache
- is returned in *IX_P (if IX_P is not NULL), and,
- - the function returns true.
-
- If DATA is not found:
- - *INCLUDE_IX_P is set to -1 (if INCLUDE_IX_P is not NULL),
- - *IX_P is set to -1 (if IX_P is not NULL), and,
- - the function returns false. */
-
-pph_cache_entry *
-pph_cache_lookup_in_includes (pph_stream *stream, void *data,
- unsigned *include_ix_p, unsigned *ix_p,
- enum pph_tag tag)
-{
- unsigned include_ix, ix;
- pph_stream *include;
- pph_cache_entry *e;
-
- /* When searching the external caches, do not try to find a match
- for TAG. Since this is an external cache, the parser may have
- re-allocated the object pointed by DATA (e.g., when merging
- decls). In this case, TAG will be different from the tag we find
- in the cache, so instead of ICEing, we ignore the match to force
- the caller to pickle DATA. */
- e = NULL;
- FOR_EACH_VEC_ELT (pph_stream_ptr, stream->includes, include_ix, include)
- {
- e = pph_cache_lookup (&include->cache, data, &ix, PPH_null);
- if (e)
- {
- /* Only consider DATA found if its data type matches TAG. If
- not, it means that the object pointed by DATA has changed,
- so DATA will need to be re-pickled. */
- if (e->tag != tag)
- e = NULL;
- break;
- }
- }
-
- if (e == NULL)
- {
- include_ix = ix = (unsigned) -1;
- ix = (unsigned) -1;
- }
-
- if (include_ix_p)
- *include_ix_p = include_ix;
-
- if (ix_p)
- *ix_p = ix;
-
- return e;
-}
-
-
-/* Add pointer DATA with data type TAG to CACHE. If IX_P is not NULL,
- on exit *IX_P will contain the slot number where DATA is stored.
- Return the newly added entry. */
-
-pph_cache_entry *
-pph_cache_add (pph_cache *cache, void *data, unsigned *ix_p, enum pph_tag tag)
-{
- unsigned ix;
- pph_cache_entry *e;
-
- e = pph_cache_lookup (cache, data, &ix, tag);
- if (e == NULL)
- {
- ix = VEC_length (pph_cache_entry, cache->v);
- e = pph_cache_insert_at (cache, data, ix, tag);
- }
-
- if (ix_p)
- *ix_p = ix;
-
- return e;
-}
-
-
-/* Associate signature CRC with the first NBYTES of the area memory
- pointed to by slot IX of CACHE. */
-
-void
-pph_cache_sign (pph_cache *cache, unsigned ix, unsigned crc, size_t nbytes)
-{
- pph_cache_entry *e;
-
- /* Needed because xcrc32 requires an int to specify the length but
- tree_size returns size_t values. */
- gcc_assert (nbytes == (size_t) (int) nbytes);
-
- e = pph_cache_get_entry (cache, ix);
- e->crc = crc;
- e->crc_nbytes = nbytes;
-}
-
-
-/* Return a signature for tree T. Store the length of the signed area
- in *NBYTES_P. */
-
-unsigned
-pph_get_signature (tree t, size_t *nbytes_p)
-{
- tree prev_chain = NULL;
- rtx prev_rtl = NULL;
- int prev_used;
- size_t nbytes;
- unsigned crc;
-
- nbytes = tree_size (t);
- if (nbytes_p)
- *nbytes_p = nbytes;
-
- /* Preserve the value of the fields not included in the signature. */
- prev_chain = (DECL_P (t)) ? DECL_CHAIN (t) : NULL;
- prev_rtl = (HAS_RTL_P (t)) ? DECL_RTL_IF_SET (t) : NULL;
- prev_used = TREE_USED (t);
-
- /* Clear the fields not included in the signature. */
- if (DECL_P (t))
- DECL_CHAIN (t) = NULL;
- if (HAS_RTL_P (t))
- SET_DECL_RTL (t, NULL);
- TREE_USED (t) = 0;
-
- crc = xcrc32 ((const unsigned char *) t, nbytes, -1);
-
- /* Restore fields we did not include in the signature. */
- if (DECL_P (t))
- DECL_CHAIN (t) = prev_chain;
- if (HAS_RTL_P (t))
- SET_DECL_RTL (t, prev_rtl);
- TREE_USED (t) = prev_used;
-
- return crc;
-}
Index: gcc/cp/config-lang.in
===================================================================
--- gcc/cp/config-lang.in (revision 181815)
+++ gcc/cp/config-lang.in (working copy)
@@ -30,4 +30,4 @@ compilers="cc1plus\$(exeext)"
target_libs="target-libstdc++-v3"
-gtfiles="\$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.h \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-lex.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/cp/class.c \$(srcdir)/cp/cp-objcp-common.c \$(srcdir)/cp/cp-lang.c \$(srcdir)/cp/pph.h \$(srcdir)/cp/pph.c \$(srcdir)/cp/except.c"
+gtfiles="\$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.h \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-lex.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/cp/class.c \$(srcdir)/cp/cp-objcp-common.c \$(srcdir)/cp/cp-lang.c \$(srcdir)/cp/pph.h \$(srcdir)/cp/pph-core.c \$(srcdir)/cp/except.c"
Index: gcc/cp/pph-streamer-out.c
===================================================================
--- gcc/cp/pph-streamer-out.c (revision 181815)
+++ gcc/cp/pph-streamer-out.c (working copy)
@@ -1,2629 +0,0 @@
-/* Routines for writing PPH data.
- Copyright (C) 2011 Free Software Foundation, Inc.
- Contributed by Diego Novillo <dnovillo@google.com>.
-
- This file is part of GCC.
-
- GCC 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 3, or (at your option)
- any later version.
-
- GCC 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 GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "pph.h"
-#include "tree.h"
-#include "langhooks.h"
-#include "tree-iterator.h"
-#include "tree-pretty-print.h"
-#include "lto-streamer.h"
-#include "pph-streamer.h"
-#include "tree-pass.h"
-#include "version.h"
-#include "cppbuiltin.h"
-#include "cgraph.h"
-#include "parser.h"
-
-
-/****************************************************** forward declarations */
-
-
-/* Forward declarations to avoid circular references. */
-static void pph_out_merge_key_tree (pph_stream *, tree);
-
-
-/***************************************************** stream initialization */
-
-
-/* PPH stream that we are currently generating. FIXME pph, this
- global is needed because we call back from various parts of the
- compiler that do not know about PPH (e.g., some LTO callbacks,
- cp_rest_of_decl_compilation). */
-static pph_stream *pph_out_stream = NULL;
-
-
-/* Initialize buffers and tables in STREAM for writing. */
-
-void
-pph_init_write (pph_stream *stream)
-{
- stream->encoder.w.out_state = lto_new_out_decl_state ();
- lto_push_out_decl_state (stream->encoder.w.out_state);
- stream->encoder.w.decl_state_stream = XCNEW (struct lto_output_stream);
- stream->encoder.w.ob = create_output_block (LTO_section_decls);
-
- /* Associate STREAM with stream->encoder.w.ob so we can recover it from the
- streamer hooks. */
- stream->encoder.w.ob->sdata = (void *) stream;
-}
-
-
-/* Initialize the PPH writer. */
-
-void
-pph_writer_init (void)
-{
- gcc_assert (pph_out_stream == NULL);
- pph_out_stream = pph_stream_open (pph_out_file, "wb");
- if (pph_out_stream == NULL)
- fatal_error ("Cannot open PPH file %s for writing: %m", pph_out_file);
-}
-
-
-/********************************************************** primitive values */
-
-
-/* Write an unsigned char VALUE to STREAM. */
-
-static void
-pph_out_uchar (pph_stream *stream, unsigned char value)
-{
- streamer_write_char_stream (stream->encoder.w.ob->main_stream, value);
-}
-
-
-/* Write a HOST_WIDE_INT VALUE to stream. */
-
-static inline void
-pph_out_hwi (pph_stream *stream, HOST_WIDE_INT value)
-{
- streamer_write_hwi (stream->encoder.w.ob, value);
-}
-
-
-/* Write an int VALUE to stream. */
-
-static inline void
-pph_out_int (pph_stream *stream, int value)
-{
- streamer_write_hwi (stream->encoder.w.ob, value);
-}
-
-
-/* Write an unsigned HOST_WIDE_INT VALUE to STREAM. */
-
-static inline void
-pph_out_uhwi (pph_stream *stream, unsigned HOST_WIDE_INT value)
-{
- streamer_write_uhwi (stream->encoder.w.ob, value);
-}
-
-
-/* Write an unsigned int VALUE to STREAM. */
-
-void
-pph_out_uint (pph_stream *stream, unsigned int value)
-{
- streamer_write_uhwi (stream->encoder.w.ob, value);
-}
-
-
-/* Write N bytes from P to STREAM. */
-
-static void
-pph_out_bytes (pph_stream *stream, const void *p, size_t n)
-{
- lto_output_data_stream (stream->encoder.w.ob->main_stream, p, n);
-}
-
-
-/* Write string STR to STREAM. */
-
-static inline void
-pph_out_string (pph_stream *stream, const char *str)
-{
- streamer_write_string (stream->encoder.w.ob,
- stream->encoder.w.ob->main_stream, str, false);
-}
-
-
-/* Write string STR of length LEN to STREAM. */
-static inline void
-pph_out_string_with_length (pph_stream *stream, const char *str,
- unsigned int len)
-{
- streamer_write_string_with_length (stream->encoder.w.ob,
- stream->encoder.w.ob->main_stream,
- str, len + 1, false);
-}
-
-
-/* Write a bitpack BP to STREAM. */
-
-static inline void
-pph_out_bitpack (pph_stream *stream, struct bitpack_d *bp)
-{
- gcc_assert (stream->encoder.w.ob->main_stream == bp->stream);
- streamer_write_bitpack (bp);
-}
-
-
-/******************************************************** source information */
-
-
-/* Emit linenum_type LN to STREAM. */
-
-static inline void
-pph_out_linenum_type (pph_stream *stream, linenum_type ln)
-{
- pph_out_uint (stream, ln);
-}
-
-
-/* Emit source_location SL to STREAM. */
-
-static inline void
-pph_out_source_location (pph_stream *stream, source_location sl)
-{
- pph_out_uint (stream, sl);
-}
-
-
-/* Emit line table MARKER to STREAM. */
-
-static inline void
-pph_out_linetable_marker (pph_stream *stream, enum pph_linetable_marker marker)
-{
- gcc_assert (marker == (enum pph_linetable_marker)(unsigned char) marker);
- pph_out_uchar (stream, marker);
-}
-
-
-/* Emit all the fields of struct line_map_ordinary LM to STREAM. IX
- is the slot number in the line table where LM is stored. */
-
-static void
-pph_out_line_map_ordinary (pph_stream *stream, struct line_map *lm, int ix)
-{
- struct bitpack_d bp;
- int rel_includer_ix, includer_ix;
-
- pph_out_string (stream, ORDINARY_MAP_FILE_NAME (lm));
- pph_out_linenum_type (stream, ORDINARY_MAP_STARTING_LINE_NUMBER (lm));
-
- /* To support relocating this table into other translation units,
- emit a relative index to LM's includer. All the relative indices
- are positive values indicating the distance from LM to the line
- map for its includer. */
- includer_ix = ORDINARY_MAP_INCLUDER_FILE_INDEX (lm);
- if (includer_ix >= 0)
- {
- gcc_assert (includer_ix < ix);
- rel_includer_ix = ix - includer_ix;
- }
- else
- {
- /* If LM is included by index -1, it means that this is a line map
- entry for the top level file being compiled (i.e., the PPH that
- we are currently generating). The first time we find this index,
- the reader will remember the index of the current parent file
- and replace all the -1 entries with it. */
- gcc_assert (includer_ix == -1);
- rel_includer_ix = includer_ix;
- }
-
- pph_out_int (stream, rel_includer_ix);
-
- bp = bitpack_create (stream->encoder.w.ob->main_stream);
- bp_pack_value (&bp, ORDINARY_MAP_IN_SYSTEM_HEADER_P (lm), CHAR_BIT);
- bp_pack_value (&bp, ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (lm), COLUMN_BITS_BIT);
- pph_out_bitpack (stream, &bp);
-}
-
-
-/* Emit all information contained in LM to STREAM. IX is the slot number
- in the line table where LM is stored. */
-
-static void
-pph_out_line_map (pph_stream *stream, struct line_map *lm, int ix)
-{
- struct output_block *ob = stream->encoder.w.ob;
-
- pph_out_source_location (stream, lm->start_location);
- streamer_write_enum (ob->main_stream, lc_reason, LC_ENTER_MACRO, lm->reason);
-
- /* FIXME pph. We currently do not support location tracking for
- macros in PPH images. */
- gcc_assert (lm->reason != LC_ENTER_MACRO);
- pph_out_line_map_ordinary (stream, lm, ix);
-}
-
-
-/* Write a reference of INCLUDE to STREAM. Also write the START_LOCATION of
- this include in the current line_table. */
-
-static void
-pph_out_include (pph_stream *stream, pph_stream *include,
- source_location start_location)
-{
- pph_out_source_location (stream, start_location);
- pph_out_string (stream, include->name);
-}
-
-
-/* Compare filenames of a header and it's potentially corresponding pph file,
- stripping the path passed in and the extension. Returns true if HEADER_PATH
- and PPH_PATH end with the same filename. We expect HEADER_PATH to end in .h
- and PPH_PATH to end in .pph.
-
- FIXME pph: We should not need to do this if we handled include paths
- correctly, but for now the linemap holds full paths and the stream's includes
- list only holds the include name. Also, the stream's includes hold pph
- filenames where as the line_table as header filenames. */
-
-static bool
-pph_filename_eq_ignoring_path (const char *header_path, const char *pph_path)
-{
- const char *header_name = lbasename (header_path);
- const char *pph_name = lbasename (pph_path);
-
- const char *header_ext = strchr (header_name, '.');
- const char *pph_ext = strchr (pph_name, '.');
-
- unsigned int name_length;
-
- if (header_ext != NULL)
- {
- name_length = header_ext - header_name;
- gcc_assert (strcmp (header_ext, ".h") == 0);
- }
- else
- /* Some headers do not have a .h suffix, but will still
- have a .pph suffix after being pph'ed. */
- name_length = strlen (header_name);
-
- gcc_assert (strcmp (pph_ext, ".pph") == 0);
-
- /* Compare the filenames without their extension. */
- return pph_ext - pph_name == name_length
- && strncmp (header_name, pph_name, name_length) == 0;
-}
-
-
-/* Return the *NEXT_INCLUDE_IX'th pph_stream in STREAM's list of includes.
- Returns NULL if we have read all includes. Increments *NEXT_INCLUDE_IX
- when sucessful. */
-
-static inline pph_stream *
-pph_get_next_include (pph_stream *stream, unsigned int *next_incl_ix)
-{
- if (*next_incl_ix < VEC_length (pph_stream_ptr, stream->includes))
- return VEC_index (pph_stream_ptr, stream->includes, (*next_incl_ix)++);
- else
- return NULL;
-}
-
-
-/* Emit the required line_map entry (those directly related to this include)
- and some properties in the line_table to STREAM, ignoring builtin and
- command-line entries. We will write references to our direct includes
- children and skip their actual line_map entries (unless they are non-pph
- children in which case we have to write out their line_map entries as well).
- We assume stream->encoder.w.includes contains the pph headers included in the
- same order they are seen in the line_table. */
-
-static void
-pph_out_line_table_and_includes (pph_stream *stream)
-{
- unsigned int next_incl_ix = 0;
- int ix;
- pph_stream *current_include;
-
- /* Any #include should have been fully parsed and exited at this point. */
- gcc_assert (line_table->depth == 0);
-
- current_include = pph_get_next_include (stream, &next_incl_ix);
-
- for (ix = PPH_NUM_IGNORED_LINE_TABLE_ENTRIES;
- ix < (int) LINEMAPS_ORDINARY_USED (line_table);
- ix++)
- {
- struct line_map *lm = LINEMAPS_ORDINARY_MAP_AT (line_table, ix);
-
- /* FIXME pph. We currently do not support location tracking for
- macros in PPH images. */
- gcc_assert (lm->reason != LC_ENTER_MACRO);
-
- if (ix == PPH_NUM_IGNORED_LINE_TABLE_ENTRIES)
- {
- /* The first non-ignored entry should be an LC_RENAME back
- in the header after inserting the builtin and
- command-line entries. When reading the pph we want this
- to be a simple LC_ENTER as the builtin and command_line
- entries will already exist and we are now entering a
- #include. */
- gcc_assert (lm->reason == LC_RENAME);
- lm->reason = LC_ENTER;
- }
-
- /* If LM is an entry for an included PPH image, output a line table
- reference to it, so the reader can load the included image at
- this point. */
- if (current_include != NULL
- && pph_filename_eq_ignoring_path (LINEMAP_FILE (lm),
- current_include->name))
- {
- struct line_map *included_from;
-
- /* Assert that we are entering a new header file from another. */
- gcc_assert (lm->reason == LC_ENTER);
- gcc_assert (ORDINARY_MAP_INCLUDER_FILE_INDEX (lm) != -1);
-
- pph_out_linetable_marker (stream, PPH_LINETABLE_REFERENCE);
-
- pph_out_include (stream, current_include, lm->start_location);
-
- /* Since all the line table entries corresponding to
- CURRENT_INCLUDE and its #include children are emitted
- inside CURRENT_INCLUDE, we need to skip them so they do
- not get emitted in STREAM.
-
- To do this, we look for the next line map table that
- corresponds to an LC_LEAVE event back to the file that
- includes CURRENT_INCLUDE (which is represented by the
- line map LM). */
- included_from = INCLUDED_FROM (line_table, lm);
- for (ix++; ix < (int) LINEMAPS_ORDINARY_USED (line_table); ix++)
- {
- struct line_map *map = LINEMAPS_ORDINARY_MAP_AT (line_table, ix);
-
- /* When we find an LC_LEAVE map, we have two ways of
- deciding if it is an LC_LEAVE event back to
- INCLUDED_FROM. Either MAP goes to the same file name
- as INCLUDED_FROM or both MAP and INCLUDED_FROM are
- included by the same line map. Since the latter is
- faster, we check it instead of doing a string
- comparison. */
- if (map->reason == LC_LEAVE
- && ORDINARY_MAP_INCLUDER_FILE_INDEX (included_from)
- == ORDINARY_MAP_INCLUDER_FILE_INDEX (map))
- break;
- }
-
- /* We should always leave this loop before the end of the
- current line_table entries. */
- gcc_assert (ix < (int) LINEMAPS_ORDINARY_USED (line_table));
-
- current_include = pph_get_next_include (stream, &next_incl_ix);
- }
- else
- {
- pph_out_linetable_marker (stream, PPH_LINETABLE_ENTRY);
- pph_out_line_map (stream, lm, ix);
- }
-
- /* Restore changes made to the first entry above, if needed. */
- if (ix == PPH_NUM_IGNORED_LINE_TABLE_ENTRIES)
- lm->reason = LC_RENAME;
- }
-
- pph_out_linetable_marker (stream, PPH_LINETABLE_END);
-
- /* Output the number of entries written to validate on input. */
- pph_out_uint (stream, LINEMAPS_ORDINARY_USED (line_table)
- - PPH_NUM_IGNORED_LINE_TABLE_ENTRIES);
-
- /* Every PPH header included should have been seen and skipped in the
- line_table streaming above. */
- gcc_assert (next_incl_ix == VEC_length (pph_stream_ptr, stream->includes));
-
- pph_out_source_location (stream, line_table->highest_location);
- pph_out_source_location (stream, line_table->highest_line);
-
- pph_out_uint (stream, line_table->max_column_hint);
-}
-
-
-/*********************************************************** record handling */
-
-
-/* Return a PPH record marker according to whether DATA is NULL or
- it can be found in one of the caches associated with STREAM. TAG
- is the data type for DATA.
-
- If DATA is in any of the caches, return the corresponding slot in
- *IX_P. If DATA is in the cache of an image included by STREAM,
- return the image's index in *INCLUDE_IX_P.
-
- Caches are consulted in order of preference: preloaded, internal
- and external.
-
- If DATA is not found anywhere, return PPH_RECORD_START and, if
- given, set *IX_P and *INCLUDE_IX_P to -1. */
-
-static enum pph_record_marker
-pph_get_marker_for (pph_stream *stream, void *data, unsigned *include_ix_p,
- unsigned *ix_p, enum pph_tag tag)
-{
- if (ix_p)
- *ix_p = -1u;
-
- if (include_ix_p)
- *include_ix_p = -1u;
-
- /* We represent NULL pointers with PPH_RECORD_END. */
- if (data == NULL)
- return PPH_RECORD_END;
-
- /* If DATA is a pre-loaded tree node, return a pre-loaded reference
- marker. */
- if (pph_cache_lookup (NULL, data, ix_p, tag))
- return PPH_RECORD_PREF;
-
- /* If DATA is in STREAM's cache, return an internal reference marker. */
- if (pph_cache_lookup (&stream->cache, data, ix_p, tag))
- return PPH_RECORD_IREF;
-
- /* If DATA is in the cache of an included image, return an external
- reference marker. */
- if (pph_cache_lookup_in_includes (stream, data, include_ix_p, ix_p, tag))
- return PPH_RECORD_XREF;
-
- /* DATA is in none of the caches. It should be pickled out. */
- return PPH_RECORD_START;
-}
-
-
-/* Write record MARKER for data type TAG to STREAM. */
-void
-pph_out_record_marker (pph_stream *stream, enum pph_record_marker marker,
- enum pph_tag tag)
-{
- gcc_assert (marker == (enum pph_record_marker)(unsigned char) marker);
- pph_out_uchar (stream, marker);
-
- gcc_assert (tag == (enum pph_tag)(unsigned) tag);
- pph_out_uint (stream, tag);
-
- if (flag_pph_tracer >= 5)
- pph_trace_marker (marker, tag);
-}
-
-
-/* Write a reference record on STREAM. MARKER is the tag indicating
- what kind of reference to write. TAG indicates the data type to be
- stored in this record. IX is the cache slot index to write.
- INCLUDE_IX is used for PPH_RECORD_XREF records. */
-
-static inline void
-pph_out_reference_record (pph_stream *stream, enum pph_record_marker marker,
- unsigned include_ix, unsigned ix, enum pph_tag tag)
-{
- gcc_assert (marker == PPH_RECORD_END || pph_is_reference_marker (marker));
-
- pph_out_record_marker (stream, marker, tag);
-
- if (pph_is_reference_marker (marker))
- {
- if (marker == PPH_RECORD_XREF)
- {
- gcc_assert (include_ix != -1u);
- pph_out_uint (stream, include_ix);
- }
-
- gcc_assert (ix != -1u);
- pph_out_uint (stream, ix);
- }
- else
- gcc_assert (marker == PPH_RECORD_END);
-}
-
-
-/* Start a new record in STREAM for DATA with data type TAG. If DATA
- is NULL write an end-of-record marker and return true.
-
- If DATA is not NULL and did not exist in the pickle cache, add it,
- write a start-of-record marker and return true. This means that we
- could not write a reference marker to DATA and the caller should
- pickle out DATA's physical representation.
-
- If DATA existed in the cache, write a reference-record marker and
- return true. This means that we could write a reference marker to
- DATA. */
-
-static inline bool
-pph_out_start_record (pph_stream *stream, void *data, enum pph_tag tag)
-{
- unsigned include_ix, ix;
- enum pph_record_marker marker;
-
- /* Try to write a reference record first. */
- marker = pph_get_marker_for (stream, data, &include_ix, &ix, tag);
- if (marker == PPH_RECORD_END || pph_is_reference_marker (marker))
- {
- pph_out_reference_record (stream, marker, include_ix, ix, tag);
- return true;
- }
-
- /* DATA is in none of the pickle caches. Add DATA to STREAM's
- pickle cache and write the slot where we stored it in. */
- pph_cache_add (&stream->cache, data, &ix, tag);
- pph_out_record_marker (stream, PPH_RECORD_START, tag);
- pph_out_uint (stream, ix);
-
- /* The caller will have to write a physical representation for DATA. */
- return false;
-}
-
-
-/* Return true if tree node T should be added to the pickle cache. */
-
-static inline bool
-pph_cache_should_handle (tree t)
-{
- if (t)
- {
- if (TREE_CODE (t) == INTEGER_CST)
- {
- /* With the exception of some special constants that are
- pointer-compared everywhere (e.g., integer_zero_node), we
- do not want constants in the cache. Their physical
- representation is smaller than a cache reference record
- and they can also trick the cache in similar ways to
- builtins (read below). */
- return false;
- }
- else if (streamer_handle_as_builtin_p (t))
- {
- /* We do not want builtins in the cache for two reasons:
-
- - They never need pickling. Much like pre-loaded tree
- nodes, builtins are pre-built by the compiler and
- accessible with their class and code.
-
- - They can trick the cache. When possible, user-provided
- functions are generally replaced by their builtin
- counterparts (e.g., strcmp, malloc, etc). When this
- happens, the writer cache will store in its cache two
- different expressions, one for the user provided
- function and another for the builtin itself. However,
- when written out to the PPH image, they both get
- emitted as a reference to the builtin. Therefore, when
- the reader tries to instantiate the second copy, it
- tries to store the same tree in two different cache
- slots (and proceeds to ICE in pph_cache_insert_at). */
- return false;
- }
- }
-
- return true;
-}
-
-
-/* Start a record for tree node T in STREAM. This is like
- pph_out_start_record, but it filters certain special trees that
- should never be added to the cache. Additionally, instead of
- returning a boolean value indicating whether pickling should be
- done, it returns the actual marker used to start the record. */
-
-static inline enum pph_record_marker
-pph_out_start_tree_record (pph_stream *stream, tree t)
-{
- unsigned include_ix, ix;
- enum pph_record_marker marker;
- enum pph_tag tag;
-
- /* Determine what kind of record we will be writing. */
- tag = pph_tree_code_to_tag (t);
- marker = pph_get_marker_for (stream, t, &include_ix, &ix, tag);
-
- /* Signed tree nodes that have been read from an external PPH image
- may have mutated while parsing this header. In that case,
- we need to write a mutated reference record and re-pickle the
- tree. */
- if (marker == PPH_RECORD_XREF && tree_needs_signature (t))
- {
- pph_cache *cache = pph_cache_select (stream, marker, include_ix);
- pph_cache_entry *e = pph_cache_get_entry (cache, ix);
- unsigned crc = pph_get_signature (t, NULL);
- if (crc != e->crc)
- marker = PPH_RECORD_START_MUTATED;
- }
-
- /* If we are about to write an internal reference for a mergeable
- tree, it means that we have already written the merge key for it.
- Check whether we still need to write its merge body. If so,
- MARKER should be PPH_RECORD_START_MERGE_BODY. */
- if (marker == PPH_RECORD_IREF && pph_tree_is_mergeable (t))
- {
- pph_cache_entry *e = pph_cache_get_entry (&stream->cache, ix);
- if (e->needs_merge_body)
- {
- marker = PPH_RECORD_START_MERGE_BODY;
- e->needs_merge_body = false;
- }
- }
-
- /* Write a record header according to the value of MARKER. */
- if (marker == PPH_RECORD_END || pph_is_reference_marker (marker))
- pph_out_reference_record (stream, marker, include_ix, ix, tag);
- else if (marker == PPH_RECORD_START || marker == PPH_RECORD_START_MERGE_BODY)
- {
- /* We want to prevent some trees from hitting the cache.
- For example, we do not want to cache regular constants (as
- their representation is actually smaller than a cache
- reference), but some constants are special and need to
- always be shared (e.g., integer_zero_node). Those special
- constants are pre-loaded in STREAM->PRELOADED_CACHE. */
- if (!pph_cache_should_handle (t))
- marker = PPH_RECORD_START_NO_CACHE;
-
- pph_out_record_marker (stream, marker, tag);
-
- if (marker == PPH_RECORD_START || marker == PPH_RECORD_START_MERGE_BODY)
- {
- unsigned ix;
- pph_cache_add (&stream->cache, t, &ix, tag);
- pph_out_uint (stream, ix);
- }
- }
- else if (marker == PPH_RECORD_START_MUTATED)
- {
- unsigned int internal_ix;
-
- /* We found T in an external PPH file, but it has mutated since
- we originally read it. We are going to write out T again,
- but the reader should not re-allocate T, rather it should
- read the contents of T on top of the existing address.
-
- We also add T to STREAM's internal cache so further
- references go to it rather than the external version.
- Note that although we add an entry for T in STREAM's internal
- cache, the reference we write to the stream is to the
- external version of T. This way the reader will get the
- location of T from the external reference and overwrite it
- with the contents that we are going to write here. */
- pph_cache_add (&stream->cache, t, &internal_ix, tag);
- pph_out_record_marker (stream, marker, tag);
-
- /* Write the location of T in the external cache. */
- gcc_assert (include_ix != -1u);
- pph_out_uint (stream, include_ix);
-
- gcc_assert (ix != -1u);
- pph_out_uint (stream, ix);
-
- /* Now write the location of the new version of T in the
- internal cache. */
- pph_out_uint (stream, internal_ix);
- }
- else
- gcc_unreachable ();
-
- return marker;
-}
-
-
-/* Start a merge key record for EXPR on STREAM. */
-
-static bool
-pph_out_start_merge_key_record (pph_stream *stream, tree expr)
-{
- enum pph_tag tag;
- enum pph_record_marker marker;
- pph_cache_entry *e;
- unsigned include_ix, ix;
-
- tag = pph_tree_code_to_tag (expr);
- marker = pph_get_marker_for (stream, expr, &include_ix, &ix, tag);
-
- if (marker == PPH_RECORD_END || pph_is_reference_marker (marker))
- {
- pph_out_reference_record (stream, marker, include_ix, ix, tag);
- return true;
- }
-
- /* This should be the first time that we try to write EXPR. */
- gcc_assert (marker == PPH_RECORD_START);
-
- pph_out_record_marker (stream, PPH_RECORD_START_MERGE_KEY, tag);
- e = pph_cache_add (&stream->cache, expr, &ix, tag);
- e->needs_merge_body = true;
- pph_out_uint (stream, ix);
- return false;
-}
-
-
-
-/********************************************************** lexical elements */
-
-
-/* Write location LOC of length to STREAM. */
-
-void
-pph_out_location (pph_stream *stream, location_t loc)
-{
- /* FIXME pph: we are streaming builtin locations, which implies that we are
- streaming some builtins, we probably want to figure out what those are and
- simply add them to the cache in the preload. */
- struct bitpack_d bp;
- struct line_map *map;
- location_t first_non_builtin_loc;
-
- map = LINEMAPS_ORDINARY_MAP_AT (line_table,
- PPH_NUM_IGNORED_LINE_TABLE_ENTRIES);
- first_non_builtin_loc = MAP_START_LOCATION (map);
-
- bp = bitpack_create (stream->encoder.w.ob->main_stream);
- if (loc < first_non_builtin_loc)
- {
- /* We should never stream out trees with locations between builtins
- and user locations (e.g. <command-line>). */
- gcc_assert (loc <= BUILTINS_LOCATION);
- bp_pack_value (&bp, true, 1);
- }
- else
- bp_pack_value (&bp, false, 1);
-
- pph_out_bitpack (stream, &bp);
- pph_out_uhwi (stream, loc);
-}
-
-
-/* Save the tree associated with TOKEN to STREAM. */
-
-static void
-pph_out_token_value (pph_stream *stream, cp_token *token)
-{
- tree val;
-
- val = token->u.value;
- switch (token->type)
- {
- case CPP_TEMPLATE_ID:
- case CPP_NESTED_NAME_SPECIFIER:
- /* FIXME pph - Need to handle struct tree_check. */
- break;
-
- case CPP_KEYWORD:
- /* Nothing to do. We will reconstruct the keyword from
- ridpointers[token->keyword] at load time. */
- break;
-
- case CPP_NAME:
- case CPP_CHAR:
- case CPP_WCHAR:
- case CPP_CHAR16:
- case CPP_CHAR32:
- case CPP_NUMBER:
- case CPP_STRING:
- case CPP_WSTRING:
- case CPP_STRING16:
- case CPP_STRING32:
- pph_out_tree (stream, val);
- break;
-
- case CPP_PRAGMA:
- /* Nothing to do. Field pragma_kind has already been written. */
- break;
-
- default:
- gcc_assert (token->u.value == NULL);
- pph_out_bytes (stream, &token->u.value, sizeof (token->u.value));
- }
-}
-
-
-/* Save TOKEN on file F. Return the number of bytes written on F. */
-
-static void
-pph_out_token (pph_stream *f, cp_token *token)
-{
- /* Do not write out the final field in TOKEN. It contains
- pointers that need to be pickled separately.
-
- FIXME pph - Need to also emit the location_t table so we can
- reconstruct it when reading the PTH state. */
- pph_out_bytes (f, token, sizeof (cp_token) - sizeof (void *));
- pph_out_token_value (f, token);
-}
-
-
-/* Save all the tokens in CACHE to PPH stream F. */
-
-static void
-pph_out_token_cache (pph_stream *f, cp_token_cache *cache)
-{
- unsigned i, num;
- cp_token *tok;
-
- if (cache == NULL)
- {
- pph_out_uint (f, 0);
- return;
- }
-
- for (num = 0, tok = cache->first; tok != cache->last; tok++)
- num++;
-
- pph_out_uint (f, num);
- for (i = 0, tok = cache->first; i < num; tok++, i++)
- pph_out_token (f, tok);
-}
-
-
-/******************************************************************* vectors */
-
-/* Note that we use the same format used by streamer_write_chain.
- This is to support pph_out_chain_filtered, which writes the
- filtered chain as a VEC. Since the reader always reads chains
- using streamer_read_chain, we have to write VECs in exactly the
- same way as tree chains. */
-
-/* Return true if T matches FILTER for STREAM. */
-
-static inline bool
-pph_tree_matches (pph_stream *stream, tree t, unsigned filter)
-{
- if ((filter & PPHF_NO_BUILTINS)
- && DECL_P (t)
- && DECL_IS_BUILTIN (t))
- return false;
-
- if ((filter & PPHF_NO_PREFS)
- && pph_cache_lookup (NULL, t, NULL, pph_tree_code_to_tag (t)))
- return false;
-
- if ((filter & PPHF_NO_XREFS)
- && pph_cache_lookup_in_includes (stream, t, NULL, NULL,
- pph_tree_code_to_tag (t)))
- return false;
-
- return true;
-}
-
-
-/* Return a heap vector with all the trees in V that match FILTER.
- The caller is responsible for freeing the returned vector. */
-
-static inline VEC(tree,heap) *
-vec2vec_filter (pph_stream *stream, VEC(tree,gc) *v, unsigned filter)
-{
- unsigned i;
- tree t;
- VEC(tree, heap) *filtered_v = NULL;
-
- /* Do not accept the nil filter. The caller is responsible for
- freeing the returned vector and they may inadvertently free
- a vector they assumed to be allocated by this function. */
- gcc_assert (filter != PPHF_NONE);
-
- /* Collect all the nodes that match the filter. */
- FOR_EACH_VEC_ELT (tree, v, i, t)
- if (pph_tree_matches (stream, t, filter))
- VEC_safe_push (tree, heap, filtered_v, t);
-
- return filtered_v;
-}
-
-
-/* Write all the trees in VEC V to STREAM. */
-
-static void
-pph_out_tree_vec (pph_stream *stream, VEC(tree,gc) *v)
-{
- unsigned i;
- tree t;
- pph_out_hwi (stream, VEC_length (tree, v));
- FOR_EACH_VEC_ELT (tree, v, i, t)
- pph_out_tree (stream, t);
-}
-
-
-/* Write all the trees in VEC V to STREAM.
- Clear TREE_CHAIN on every element written out (this is to support
- writing chains, as they are supposed to be re-chained by the reader). */
-
-static void
-pph_out_tree_vec_unchain (pph_stream *stream, VEC(tree,gc) *v)
-{
- unsigned i;
- tree t;
- pph_out_hwi (stream, VEC_length (tree, v));
- FOR_EACH_VEC_ELT (tree, v, i, t)
- {
- tree prev = TREE_CHAIN (t);
- TREE_CHAIN (t) = NULL;
- pph_out_tree (stream, t);
- TREE_CHAIN (t) = prev;
- }
-}
-
-
-/* Write all the merge keys for trees in VEC V to STREAM. The keys
- must go out in declaration order, i.e. reversed. */
-
-static void
-pph_out_merge_key_vec (pph_stream *stream, VEC(tree,gc) *v)
-{
- unsigned i;
- tree t;
- pph_out_hwi (stream, VEC_length (tree, v));
- FOR_EACH_VEC_ELT_REVERSE (tree, v, i, t)
- pph_out_merge_key_tree (stream, t);
-}
-
-
-/* Write all the merge bodies for trees in VEC V to STREAM. The bodies
- should/must go out in declaration order, i.e. reversed. */
-
-static void
-pph_out_merge_body_vec (pph_stream *stream, VEC(tree,gc) *v)
-{
- unsigned i;
- tree t;
- pph_out_hwi (stream, VEC_length (tree, v));
- FOR_EACH_VEC_ELT_REVERSE (tree, v, i, t)
- pph_out_tree (stream, t);
-}
-
-
-/* Write all the trees in VEC V that match FILTER to STREAM. */
-
-static void
-pph_out_tree_vec_filtered (pph_stream *stream, VEC(tree,gc) *v, unsigned filter)
-{
- if (filter == PPHF_NONE)
- pph_out_tree_vec (stream, v);
- else
- {
- VEC(tree,heap) *w = vec2vec_filter (stream, v, filter);
- pph_out_tree_vec (stream, (VEC(tree,gc) *)w);
- VEC_free (tree, heap, w);
- }
-}
-
-
-/* Write all the qualified_typedef_usage_t in VEC V to STREAM. */
-
-static void
-pph_out_qual_use_vec (pph_stream *stream, VEC(qualified_typedef_usage_t,gc) *v)
-{
- unsigned i;
- qualified_typedef_usage_t *q;
-
- pph_out_uint (stream, VEC_length (qualified_typedef_usage_t, v));
- FOR_EACH_VEC_ELT (qualified_typedef_usage_t, v, i, q)
- {
- pph_out_tree (stream, q->typedef_decl);
- pph_out_tree (stream, q->context);
- pph_out_location (stream, q->locus);
- }
-}
-
-
-/* Write the vector V of tree_pair_s instances to STREAM. */
-
-static void
-pph_out_tree_pair_vec (pph_stream *stream, VEC(tree_pair_s,gc) *v)
-{
- unsigned i;
- tree_pair_s *p;
-
- pph_out_uint (stream, VEC_length (tree_pair_s, v));
- FOR_EACH_VEC_ELT (tree_pair_s, v, i, p)
- {
- pph_out_tree (stream, p->purpose);
- pph_out_tree (stream, p->value);
- }
-}
-
-
-/******************************************************************** chains */
-
-/* Convert a CHAIN to a VEC by copying only the nodes that match FILTER
- for STREAM. */
-
-static VEC(tree,heap) *
-chain2vec_filter (pph_stream *stream, tree chain, unsigned filter)
-{
- tree t;
- VEC(tree,heap) *v = NULL;
-
- /* Do not accept the nil filter. The caller is responsible for
- freeing the returned vector and they may inadvertently free
- a vector they assumed to be allocated by this function. */
- /* FIXME crowl: gcc_assert (filter != PPHF_NONE); */
-
- for (t = chain; t; t = TREE_CHAIN (t))
- if (pph_tree_matches (stream, t, filter))
- VEC_safe_push (tree, heap, v, t);
-
- return v;
-}
-
-
-/* Convert a CHAIN to a VEC by copying the nodes. */
-
-static VEC(tree,heap) *
-chain2vec (tree chain)
-{
- tree t;
- VEC(tree,heap) *v = NULL;
-
- for (t = chain; t; t = TREE_CHAIN (t))
- VEC_safe_push (tree, heap, v, t);
-
- return v;
-}
-
-
-/* Write a chain of trees to STREAM starting with FIRST. */
-
-static void
-pph_out_chain (pph_stream *stream, tree first)
-{
- streamer_write_chain (stream->encoder.w.ob, first, false);
-}
-
-
-/* Write a chain of trees to stream starting with FIRST. Only write
- the trees that match FILTER. */
-
-static void
-pph_out_chain_filtered (pph_stream *stream, tree first, unsigned filter)
-{
- VEC(tree,heap) *w = chain2vec_filter (stream, first, filter);
- pph_out_tree_vec_unchain (stream, (VEC(tree,gc) *)w);
- VEC_free (tree, heap, w);
-}
-
-
-/* Write, in reverse, a chain of merge keys to STREAM starting
- with the last element of CHAIN. Only write the trees that match
- FILTER. */
-
-static void
-pph_out_merge_key_chain (pph_stream *stream, tree chain, unsigned filter)
-{
- VEC(tree,heap) *w;
- if (filter == PPHF_NONE)
- w = chain2vec (chain);
- else
- w = chain2vec_filter (stream, chain, filter);
- pph_out_merge_key_vec (stream, (VEC(tree,gc) *)w);
- VEC_free (tree, heap, w);
-}
-
-
-/* Write, in reverse, a chain of merge bodies to STREAM starting
- with the last element of CHAIN. Only write the trees that match
- FILTER. */
-
-static void
-pph_out_merge_body_chain (pph_stream *stream, tree chain, unsigned filter)
-{
- VEC(tree,heap) *w;
- if (filter == PPHF_NONE)
- w = chain2vec (chain);
- else
- w = chain2vec_filter (stream, chain, filter);
- pph_out_merge_body_vec (stream, (VEC(tree,gc) *)w);
- VEC_free (tree, heap, w);
-}
-
-
-/****************************************************************** bindings */
-
-
-/* Forward declaration to break cyclic dependencies. */
-static void pph_out_binding_level (pph_stream *, cp_binding_level *, unsigned);
-
-
-/* Helper for pph_out_cxx_binding. STREAM and CB are as in
- pph_out_cxx_binding. */
-
-static void
-pph_out_cxx_binding_1 (pph_stream *stream, cxx_binding *cb)
-{
- struct bitpack_d bp;
-
- if (pph_out_start_record (stream, cb, PPH_cxx_binding))
- return;
-
- pph_out_tree (stream, cb->value);
- pph_out_tree (stream, cb->type);
- pph_out_binding_level (stream, cb->scope, PPHF_NONE);
- bp = bitpack_create (stream->encoder.w.ob->main_stream);
- bp_pack_value (&bp, cb->value_is_inherited, 1);
- bp_pack_value (&bp, cb->is_local, 1);
- pph_out_bitpack (stream, &bp);
-}
-
-
-/* Write all the fields of cxx_binding instance CB to STREAM. */
-
-static void
-pph_out_cxx_binding (pph_stream *stream, cxx_binding *cb)
-{
- cxx_binding *prev;
-
- /* Write the current binding first. */
- pph_out_cxx_binding_1 (stream, cb);
-
- /* Write the list of previous bindings. */
- for (prev = cb ? cb->previous : NULL; prev; prev = prev->previous)
- pph_out_cxx_binding_1 (stream, prev);
-
- /* Mark the end of the list (if there was a list). */
- if (cb)
- pph_out_cxx_binding_1 (stream, NULL);
-}
-
-
-/* Write all the fields of cp_class_binding instance CB to STREAM. */
-
-static void
-pph_out_class_binding (pph_stream *stream, cp_class_binding *cb)
-{
- if (pph_out_start_record (stream, cb, PPH_cp_class_binding))
- return;
-
- pph_out_cxx_binding (stream, cb->base);
- pph_out_tree (stream, cb->identifier);
-}
-
-
-/* Write all the fields of cp_label_binding instance LB to STREAM. */
-
-static void
-pph_out_label_binding (pph_stream *stream, cp_label_binding *lb)
-{
- if (pph_out_start_record (stream, lb, PPH_cp_label_binding))
- return;
-
- pph_out_tree (stream, lb->label);
- pph_out_tree (stream, lb->prev_value);
-}
-
-
-/* Helper for pph_out_binding_level. Write the fields of BL to
- STREAM. Do not emit any nodes in BL that do not match FILTER. */
-
-static void
-pph_out_binding_level_1 (pph_stream *stream, cp_binding_level *bl,
- unsigned filter)
-{
- unsigned i;
- cp_class_binding *cs;
- cp_label_binding *sl;
- struct bitpack_d bp;
-
- pph_out_tree (stream, bl->this_entity);
-
- pph_out_uint (stream, VEC_length (cp_class_binding, bl->class_shadowed));
- FOR_EACH_VEC_ELT (cp_class_binding, bl->class_shadowed, i, cs)
- pph_out_class_binding (stream, cs);
-
- pph_out_tree (stream, bl->type_shadowed);
-
- pph_out_uint (stream, VEC_length (cp_label_binding, bl->shadowed_labels));
- FOR_EACH_VEC_ELT (cp_label_binding, bl->shadowed_labels, i, sl)
- pph_out_label_binding (stream, sl);
-
- pph_out_tree (stream, bl->blocks);
- pph_out_binding_level (stream, bl->level_chain, filter);
- pph_out_tree_vec (stream, bl->dead_vars_from_for);
- pph_out_chain (stream, bl->statement_list);
- pph_out_uint (stream, bl->binding_depth);
-
- bp = bitpack_create (stream->encoder.w.ob->main_stream);
- bp_pack_value (&bp, bl->kind, 4);
- bp_pack_value (&bp, bl->keep, 1);
- bp_pack_value (&bp, bl->more_cleanups_ok, 1);
- bp_pack_value (&bp, bl->have_cleanups, 1);
- pph_out_bitpack (stream, &bp);
-}
-
-
-/* Write all the fields of cp_binding_level instance BL to STREAM for the
- non-merging case. Do not emit any nodes in BL that do not match FILTER. */
-
-static void
-pph_out_binding_level (pph_stream *stream, cp_binding_level *bl,
- unsigned filter)
-{
- if (pph_out_start_record (stream, bl, PPH_cp_binding_level))
- return;
-
- pph_out_chain_filtered (stream, bl->names, filter);
- pph_out_chain_filtered (stream, bl->namespaces, filter);
- pph_out_chain_filtered (stream, bl->usings, filter);
- pph_out_chain_filtered (stream, bl->using_directives, filter);
- pph_out_tree_vec_filtered (stream, bl->static_decls, filter);
- pph_out_binding_level_1 (stream, bl, filter);
-}
-
-
-/* Write an index of mergeable objects from cp_binding_level BL to STREAM. */
-
-static void
-pph_out_binding_merge_keys (pph_stream *stream, cp_binding_level *bl)
-{
- unsigned filter = PPHF_NO_XREFS | PPHF_NO_PREFS | PPHF_NO_BUILTINS;
- pph_out_merge_key_chain (stream, bl->names, filter);
- pph_out_merge_key_chain (stream, bl->namespaces, filter);
- pph_out_merge_key_chain (stream, bl->usings, filter);
- pph_out_merge_key_chain (stream, bl->using_directives, filter);
-}
-
-
-/* Write bodies of mergeable objects from cp_binding_level BL to STREAM. */
-
-static void
-pph_out_binding_merge_bodies (pph_stream *stream, cp_binding_level *bl)
-{
- unsigned filter = PPHF_NO_XREFS | PPHF_NO_PREFS | PPHF_NO_BUILTINS;
- pph_out_merge_body_chain (stream, bl->names, filter);
- pph_out_merge_body_chain (stream, bl->namespaces, filter);
- pph_out_merge_body_chain (stream, bl->usings, filter);
- pph_out_merge_body_chain (stream, bl->using_directives, filter);
- pph_out_tree_vec_filtered (stream, bl->static_decls, filter);
- pph_out_binding_level_1 (stream, bl, filter);
-}
-
-
-/********************************************************** tree aux classes */
-
-
-/* Write all the fields of language_function instance LF to STREAM. */
-
-static void
-pph_out_language_function (pph_stream *stream, struct language_function *lf)
-{
- struct bitpack_d bp;
-
- if (pph_out_start_record (stream, lf, PPH_language_function))
- return;
-
- pph_out_tree_vec (stream, lf->base.x_stmt_tree.x_cur_stmt_list);
- pph_out_uint (stream, lf->base.x_stmt_tree.stmts_are_full_exprs_p);
- pph_out_tree (stream, lf->x_cdtor_label);
- pph_out_tree (stream, lf->x_current_class_ptr);
- pph_out_tree (stream, lf->x_current_class_ref);
- pph_out_tree (stream, lf->x_eh_spec_block);
- pph_out_tree (stream, lf->x_in_charge_parm);
- pph_out_tree (stream, lf->x_vtt_parm);
- pph_out_tree (stream, lf->x_return_value);
- bp = bitpack_create (stream->encoder.w.ob->main_stream);
- bp_pack_value (&bp, lf->returns_value, 1);
- bp_pack_value (&bp, lf->returns_null, 1);
- bp_pack_value (&bp, lf->returns_abnormally, 1);
- bp_pack_value (&bp, lf->x_in_function_try_handler, 1);
- bp_pack_value (&bp, lf->x_in_base_initializer, 1);
- bp_pack_value (&bp, lf->can_throw, 1);
- pph_out_bitpack (stream, &bp);
-
- /* FIXME pph. We are not writing lf->x_named_labels. */
-
- pph_out_binding_level (stream, lf->bindings, PPHF_NONE);
- pph_out_tree_vec (stream, lf->x_local_names);
-
- /* FIXME pph. We are not writing lf->extern_decl_map. */
-}
-
-
-/* A callback of htab_traverse. Just extracts a (type) tree from SLOT
- and writes it out for PPH. */
-
-struct pph_tree_info {
- pph_stream *stream;
-};
-
-static int
-pph_out_used_types_slot (void **slot, void *aux)
-{
- struct pph_tree_info *pti = (struct pph_tree_info *) aux;
- pph_out_tree (pti->stream, (tree) *slot);
- return 1;
-}
-
-
-/* Write applicable fields of struct function instance FN to STREAM. */
-
-static void
-pph_out_struct_function (pph_stream *stream, struct function *fn)
-{
- struct pph_tree_info pti;
-
- if (pph_out_start_record (stream, fn, PPH_function))
- return;
-
- pph_out_tree (stream, fn->decl);
- output_struct_function_base (stream->encoder.w.ob, fn);
-
- /* struct eh_status *eh; -- ignored */
- gcc_assert (fn->cfg == NULL);
- gcc_assert (fn->gimple_body == NULL);
- gcc_assert (fn->gimple_df == NULL);
- gcc_assert (fn->x_current_loops == NULL);
- gcc_assert (fn->su == NULL);
- /* htab_t value_histograms; -- ignored */
- /* tree decl; -- ignored */
- /* tree static_chain_decl; -- in base */
- /* tree nonlocal_goto_save_area; -- in base */
- /* VEC(tree,gc) *local_decls; -- in base */
- /* struct machine_function *machine; -- ignored */
- pph_out_language_function (stream, fn->language);
-
- /* FIXME pph: We would like to detect improper sharing here. */
- if (fn->used_types_hash)
- {
- /* FIXME pph: This write may be unstable. */
- pph_out_uint (stream, htab_elements (fn->used_types_hash));
- pti.stream = stream;
- htab_traverse_noresize (fn->used_types_hash, pph_out_used_types_slot,
- &pti);
- }
- else
- pph_out_uint (stream, 0);
-
- gcc_assert (fn->last_stmt_uid == 0);
- /* int funcdef_no; -- ignored */
- /* location_t function_start_locus; -- in base */
- /* location_t function_end_locus; -- in base */
- /* unsigned int curr_properties; -- in base */
- /* unsigned int last_verified; -- ignored */
- /* const char *cannot_be_copied_reason; -- ignored */
-
- /* unsigned int va_list_gpr_size : 8; -- in base */
- /* unsigned int va_list_fpr_size : 8; -- in base */
- /* unsigned int calls_setjmp : 1; -- in base */
- /* unsigned int calls_alloca : 1; -- in base */
- /* unsigned int has_nonlocal_label : 1; -- in base */
- /* unsigned int cannot_be_copied_set : 1; -- ignored */
- /* unsigned int stdarg : 1; -- in base */
- /* unsigned int after_inlining : 1; -- in base */
- /* unsigned int always_inline_functions_inlined : 1; -- in base */
- /* unsigned int can_throw_non_call_exceptions : 1; -- in base */
- /* unsigned int returns_struct : 1; -- in base */
- /* unsigned int returns_pcc_struct : 1; -- in base */
- /* unsigned int after_tree_profile : 1; -- in base */
- /* unsigned int has_local_explicit_reg_vars : 1; -- in base */
- /* unsigned int is_thunk : 1; -- in base */
-}
-
-
-/* Write all the fields in lang_decl_base instance LDB to OB. */
-
-static void
-pph_out_ld_base (pph_stream *stream, struct lang_decl_base *ldb)
-{
- struct bitpack_d bp;
-
- bp = bitpack_create (stream->encoder.w.ob->main_stream);
- bp_pack_value (&bp, ldb->selector, 16);
- bp_pack_value (&bp, ldb->language, 4);
- bp_pack_value (&bp, ldb->use_template, 2);
- bp_pack_value (&bp, ldb->not_really_extern, 1);
- bp_pack_value (&bp, ldb->initialized_in_class, 1);
- bp_pack_value (&bp, ldb->repo_available_p, 1);
- bp_pack_value (&bp, ldb->threadprivate_or_deleted_p, 1);
- bp_pack_value (&bp, ldb->anticipated_p, 1);
- bp_pack_value (&bp, ldb->friend_attr, 1);
- bp_pack_value (&bp, ldb->template_conv_p, 1);
- bp_pack_value (&bp, ldb->odr_used, 1);
- bp_pack_value (&bp, ldb->u2sel, 1);
- pph_out_bitpack (stream, &bp);
-}
-
-
-/* Write all the fields in lang_decl_min instance LDM to STREAM. */
-
-static void
-pph_out_ld_min (pph_stream *stream, struct lang_decl_min *ldm)
-{
- pph_out_tree (stream, ldm->template_info);
- if (ldm->base.u2sel == 0)
- pph_out_tree (stream, ldm->u2.access);
- else if (ldm->base.u2sel == 1)
- pph_out_uint (stream, ldm->u2.discriminator);
- else
- gcc_unreachable ();
-}
-
-
-/* Write all the fields of lang_decl_fn instance LDF to STREAM. */
-
-static void
-pph_out_ld_fn (pph_stream *stream, struct lang_decl_fn *ldf)
-{
- struct bitpack_d bp;
-
- /* Write all the fields in lang_decl_min. */
- pph_out_ld_min (stream, &ldf->min);
-
- bp = bitpack_create (stream->encoder.w.ob->main_stream);
- bp_pack_value (&bp, ldf->operator_code, 16);
- bp_pack_value (&bp, ldf->global_ctor_p, 1);
- bp_pack_value (&bp, ldf->global_dtor_p, 1);
- bp_pack_value (&bp, ldf->constructor_attr, 1);
- bp_pack_value (&bp, ldf->destructor_attr, 1);
- bp_pack_value (&bp, ldf->assignment_operator_p, 1);
- bp_pack_value (&bp, ldf->static_function, 1);
- bp_pack_value (&bp, ldf->pure_virtual, 1);
- bp_pack_value (&bp, ldf->defaulted_p, 1);
- bp_pack_value (&bp, ldf->has_in_charge_parm_p, 1);
- bp_pack_value (&bp, ldf->has_vtt_parm_p, 1);
- bp_pack_value (&bp, ldf->pending_inline_p, 1);
- bp_pack_value (&bp, ldf->nonconverting, 1);
- bp_pack_value (&bp, ldf->thunk_p, 1);
- bp_pack_value (&bp, ldf->this_thunk_p, 1);
- bp_pack_value (&bp, ldf->hidden_friend_p, 1);
- pph_out_bitpack (stream, &bp);
-
- pph_out_tree (stream, ldf->befriending_classes);
- pph_out_tree (stream, ldf->context);
-
- if (ldf->thunk_p == 0)
- pph_out_tree (stream, ldf->u5.cloned_function);
- else if (ldf->thunk_p == 1)
- pph_out_uint (stream, ldf->u5.fixed_offset);
- else
- gcc_unreachable ();
-
- if (ldf->pending_inline_p == 1)
- pph_out_token_cache (stream, ldf->u.pending_inline_info);
- else if (ldf->pending_inline_p == 0)
- pph_out_language_function (stream, ldf->u.saved_language_function);
-}
-
-
-/* Write all the fields of lang_decl_ns instance LDNS to STREAM. */
-
-static void
-pph_out_ld_ns (pph_stream *stream, struct lang_decl_ns *ldns)
-{
- pph_out_binding_level (stream, ldns->level, PPHF_NONE);
-}
-
-
-/* Write all the fields of lang_decl_parm instance LDP to STREAM. */
-
-static void
-pph_out_ld_parm (pph_stream *stream, struct lang_decl_parm *ldp)
-{
- pph_out_uint (stream, ldp->level);
- pph_out_uint (stream, ldp->index);
-}
-
-
-/* Write all the lang-specific data in DECL to STREAM. */
-
-static void
-pph_out_lang_specific (pph_stream *stream, tree decl)
-{
- struct lang_decl *ld;
- struct lang_decl_base *ldb;
-
- ld = DECL_LANG_SPECIFIC (decl);
- if (pph_out_start_record (stream, ld, PPH_lang_decl))
- return;
-
- /* Write all the fields in lang_decl_base. */
- ldb = &ld->u.base;
- pph_out_ld_base (stream, ldb);
-
- if (ldb->selector == 0)
- {
- /* Write all the fields in lang_decl_min. */
- pph_out_ld_min (stream, &ld->u.min);
- }
- else if (ldb->selector == 1)
- {
- /* Write all the fields in lang_decl_fn. */
- pph_out_ld_fn (stream, &ld->u.fn);
- }
- else if (ldb->selector == 2)
- {
- /* Write all the fields in lang_decl_ns. */
- pph_out_ld_ns (stream, &ld->u.ns);
- }
- else if (ldb->selector == 3)
- {
- /* Write all the fields in lang_decl_parm. */
- pph_out_ld_parm (stream, &ld->u.parm);
- }
- else
- gcc_unreachable ();
-}
-
-
-/********************************************************* tree base classes */
-
-
-/* Write out the tree_common fields from T to STREAM. */
-
-static void
-pph_out_tree_common (pph_stream *stream, tree t)
-{
- /* The chain field in DECLs is handled separately. Make sure this
- is never called with a DECL. */
- gcc_assert (!DECL_P (t));
-
- /* The 'struct tree_typed typed' base class is handled in LTO. */
- pph_out_tree (stream, TREE_CHAIN (t));
-}
-
-
-/* Write all the fields in lang_type_header instance LTH to STREAM. */
-
-static void
-pph_out_lang_type_header (pph_stream *stream, struct lang_type_header *lth)
-{
- struct bitpack_d bp;
-
- bp = bitpack_create (stream->encoder.w.ob->main_stream);
- bp_pack_value (&bp, lth->is_lang_type_class, 1);
- bp_pack_value (&bp, lth->has_type_conversion, 1);
- bp_pack_value (&bp, lth->has_copy_ctor, 1);
- bp_pack_value (&bp, lth->has_default_ctor, 1);
- bp_pack_value (&bp, lth->const_needs_init, 1);
- bp_pack_value (&bp, lth->ref_needs_init, 1);
- bp_pack_value (&bp, lth->has_const_copy_assign, 1);
- pph_out_bitpack (stream, &bp);
-}
-
-
-/* Write a struct sorted_fields_type instance SFT to STREAM. */
-
-static void
-pph_out_sorted_fields_type (pph_stream *stream, struct sorted_fields_type *sft)
-{
- int i;
-
- if (pph_out_start_record (stream, sft, PPH_sorted_fields_type))
- return;
-
- pph_out_uint (stream, sft->len);
- for (i = 0; i < sft->len; i++)
- pph_out_tree (stream, sft->elts[i]);
-}
-
-
-/* Write all the fields in lang_type_class instance LTC to STREAM. */
-
-static void
-pph_out_lang_type_class (pph_stream *stream, struct lang_type_class *ltc)
-{
- struct bitpack_d bp;
-
- pph_out_uchar (stream, ltc->align);
-
- bp = bitpack_create (stream->encoder.w.ob->main_stream);
- bp_pack_value (&bp, ltc->has_mutable, 1);
- bp_pack_value (&bp, ltc->com_interface, 1);
- bp_pack_value (&bp, ltc->non_pod_class, 1);
- bp_pack_value (&bp, ltc->nearly_empty_p, 1);
- bp_pack_value (&bp, ltc->user_align, 1);
- bp_pack_value (&bp, ltc->has_copy_assign, 1);
- bp_pack_value (&bp, ltc->has_new, 1);
- bp_pack_value (&bp, ltc->has_array_new, 1);
- bp_pack_value (&bp, ltc->gets_delete, 2);
- bp_pack_value (&bp, ltc->interface_only, 1);
- bp_pack_value (&bp, ltc->interface_unknown, 1);
- bp_pack_value (&bp, ltc->contains_empty_class_p, 1);
- bp_pack_value (&bp, ltc->anon_aggr, 1);
- bp_pack_value (&bp, ltc->non_zero_init, 1);
- bp_pack_value (&bp, ltc->empty_p, 1);
- bp_pack_value (&bp, ltc->vec_new_uses_cookie, 1);
- bp_pack_value (&bp, ltc->declared_class, 1);
- bp_pack_value (&bp, ltc->diamond_shaped, 1);
- bp_pack_value (&bp, ltc->repeated_base, 1);
- bp_pack_value (&bp, ltc->being_defined, 1);
- bp_pack_value (&bp, ltc->java_interface, 1);
- bp_pack_value (&bp, ltc->debug_requested, 1);
- bp_pack_value (&bp, ltc->fields_readonly, 1);
- bp_pack_value (&bp, ltc->use_template, 2);
- bp_pack_value (&bp, ltc->ptrmemfunc_flag, 1);
- bp_pack_value (&bp, ltc->was_anonymous, 1);
- bp_pack_value (&bp, ltc->lazy_default_ctor, 1);
- bp_pack_value (&bp, ltc->lazy_copy_ctor, 1);
- bp_pack_value (&bp, ltc->lazy_copy_assign, 1);
- bp_pack_value (&bp, ltc->lazy_destructor, 1);
- bp_pack_value (&bp, ltc->has_const_copy_ctor, 1);
- bp_pack_value (&bp, ltc->has_complex_copy_ctor, 1);
- bp_pack_value (&bp, ltc->has_complex_copy_assign, 1);
- bp_pack_value (&bp, ltc->non_aggregate, 1);
- bp_pack_value (&bp, ltc->has_complex_dflt, 1);
- bp_pack_value (&bp, ltc->has_list_ctor, 1);
- bp_pack_value (&bp, ltc->non_std_layout, 1);
- bp_pack_value (&bp, ltc->is_literal, 1);
- bp_pack_value (&bp, ltc->lazy_move_ctor, 1);
- bp_pack_value (&bp, ltc->lazy_move_assign, 1);
- bp_pack_value (&bp, ltc->has_complex_move_ctor, 1);
- bp_pack_value (&bp, ltc->has_complex_move_assign, 1);
- bp_pack_value (&bp, ltc->has_constexpr_ctor, 1);
- pph_out_bitpack (stream, &bp);
-
- pph_out_tree (stream, ltc->primary_base);
- pph_out_tree_pair_vec (stream, ltc->vcall_indices);
- pph_out_tree (stream, ltc->vtables);
- pph_out_tree (stream, ltc->typeinfo_var);
- pph_out_tree_vec (stream, ltc->vbases);
- if (!pph_out_start_record (stream, ltc->nested_udts, PPH_binding_table))
- pph_out_binding_table (stream, ltc->nested_udts);
- pph_out_tree (stream, ltc->as_base);
- pph_out_tree_vec (stream, ltc->pure_virtuals);
- pph_out_tree (stream, ltc->friend_classes);
- pph_out_tree_vec (stream, ltc->methods);
- pph_out_tree (stream, ltc->key_method);
- pph_out_tree (stream, ltc->decl_list);
- pph_out_tree (stream, ltc->template_info);
- pph_out_tree (stream, ltc->befriending_classes);
- pph_out_tree (stream, ltc->objc_info);
- pph_out_sorted_fields_type (stream, ltc->sorted_fields);
- pph_out_tree (stream, ltc->lambda_expr);
-}
-
-
-/* Write struct lang_type_ptrmem instance LTP to STREAM. */
-
-static void
-pph_out_lang_type_ptrmem (pph_stream *stream, struct lang_type_ptrmem *ltp)
-{
- pph_out_tree (stream, ltp->record);
-}
-
-
-/* Write all the lang-specific fields of TYPE to STREAM. */
-
-static void
-pph_out_lang_type (pph_stream *stream, tree type)
-{
- struct lang_type *lt;
-
- lt = TYPE_LANG_SPECIFIC (type);
- if (pph_out_start_record (stream, lt, PPH_lang_type))
- return;
-
- pph_out_lang_type_header (stream, <->u.h);
- if (lt->u.h.is_lang_type_class)
- pph_out_lang_type_class (stream, <->u.c);
- else
- pph_out_lang_type_ptrmem (stream, <->u.ptrmem);
-}
-
-
-/* Write to STREAM the body of tcc_type node TYPE. */
-
-static void
-pph_out_tcc_type (pph_stream *stream, tree type)
-{
- pph_out_lang_type (stream, type);
- pph_out_tree (stream, TYPE_POINTER_TO (type));
- pph_out_tree (stream, TYPE_REFERENCE_TO (type));
- pph_out_tree (stream, TYPE_NEXT_VARIANT (type));
- /* FIXME pph - Streaming TYPE_CANONICAL generates many type comparison
- failures. Why? */
- pph_out_tree (stream, TREE_CHAIN (type));
-
- /* The type values cache is built as constants are instantiated,
- so we only stream it on the nodes that use it for
- other purposes. */
- switch (TREE_CODE (type))
- {
- case BOUND_TEMPLATE_TEMPLATE_PARM:
- case DECLTYPE_TYPE:
- case TEMPLATE_TEMPLATE_PARM:
- case TEMPLATE_TYPE_PARM:
- case TYPENAME_TYPE:
- case TYPEOF_TYPE:
- pph_out_tree (stream, TYPE_VALUES_RAW (type));
- break;
-
- default:
- break;
- }
-}
-
-
-/* Write to STREAM the body of tcc_declaration tree DECL. */
-
-static void
-pph_out_tcc_declaration (pph_stream *stream, tree decl)
-{
- pph_out_lang_specific (stream, decl);
- pph_out_tree (stream, DECL_INITIAL (decl));
-
- /* The tree streamer only writes DECL_CHAIN for PARM_DECL nodes.
- We need to write DECL_CHAIN for variables and functions because
- they are sometimes chained together in places other than regular
- tree chains. For example in BINFO_VTABLEs, the decls are chained
- together). */
- if (TREE_CODE (decl) == VAR_DECL
- || TREE_CODE (decl) == FUNCTION_DECL)
- pph_out_tree (stream, DECL_CHAIN (decl));
-
- /* Handle some individual decl nodes. */
- switch (TREE_CODE (decl))
- {
- case FUNCTION_DECL:
- /* Note that for FUNCTION_DECLs we do not output
- DECL_STRUCT_FUNCTION here. This is emitted at the end of the
- PPH file in pph_out_symtab. This way, we will be able to
- re-instantiate them in the same order when reading the image
- (the allocation of DECL_STRUCT_FUNCTION has the side effect
- of generating function sequence numbers
- (function.funcdef_no). */
- pph_out_tree (stream, DECL_SAVED_TREE (decl));
- break;
-
- case TYPE_DECL:
- pph_out_tree (stream, DECL_ORIGINAL_TYPE (decl));
- break;
-
- case TEMPLATE_DECL:
- pph_out_tree (stream, DECL_TEMPLATE_RESULT (decl));
- pph_out_tree (stream, DECL_TEMPLATE_PARMS (decl));
- break;
-
- default:
- break;
- }
-}
-
-
-/******************************************************** tree head and body */
-
-
-/* Write the body of EXPR to STREAM. This writes out all fields not
- written by the generic tree streaming routines. */
-
-static void
-pph_out_tree_body (pph_stream *stream, tree expr)
-{
- bool handled_p;
-
- /* Write the language-independent parts of EXPR's body. */
- streamer_write_tree_body (stream->encoder.w.ob, expr, false);
-
- /* Handle common tree code classes first. */
- handled_p = true;
- switch (TREE_CODE_CLASS (TREE_CODE (expr)))
- {
- case tcc_declaration:
- pph_out_tcc_declaration (stream, expr);
- break;
-
- case tcc_type:
- pph_out_tcc_type (stream, expr);
- break;
-
- case tcc_constant:
- if (TREE_CODE (expr) == PTRMEM_CST)
- {
- pph_out_tree_common (stream, expr);
- pph_out_tree (stream, PTRMEM_CST_MEMBER (expr));
- }
- break;
-
- case tcc_expression:
- case tcc_unary:
- case tcc_binary:
- case tcc_vl_exp:
- case tcc_reference:
- case tcc_comparison:
- case tcc_statement:
- /* These tree classes are completely handled by the tree streamer. */
- break;
-
- default:
- handled_p = false;
- break;
- }
-
- /* If we've already handled the tree, we are done. */
- if (handled_p)
- return;
-
- /* Only tcc_exceptional tree codes are left to handle. */
- gcc_assert (TREE_CODE_CLASS (TREE_CODE (expr)) == tcc_exceptional);
-
- switch (TREE_CODE (expr))
- {
- case STATEMENT_LIST:
- {
- tree_stmt_iterator i;
- unsigned num_stmts;
-
- /* Compute and write the number of statements in the list. */
- for (num_stmts = 0, i = tsi_start (expr); !tsi_end_p (i); tsi_next (&i))
- num_stmts++;
-
- pph_out_uint (stream, num_stmts);
-
- /* Write the statements. */
- for (i = tsi_start (expr); !tsi_end_p (i); tsi_next (&i))
- pph_out_tree (stream, tsi_stmt (i));
- }
- break;
-
- case OVERLOAD:
- pph_out_tree_common (stream, expr);
- pph_out_tree (stream, OVL_CURRENT (expr));
- break;
-
- case IDENTIFIER_NODE:
- pph_out_cxx_binding (stream, IDENTIFIER_NAMESPACE_BINDINGS (expr));
- pph_out_cxx_binding (stream, IDENTIFIER_BINDING (expr));
- pph_out_tree (stream, IDENTIFIER_TEMPLATE (expr));
- pph_out_tree (stream, IDENTIFIER_LABEL_VALUE (expr));
- pph_out_tree (stream, REAL_IDENTIFIER_TYPE_VALUE (expr));
- break;
-
- case BASELINK:
- pph_out_tree_common (stream, expr);
- pph_out_tree (stream, BASELINK_BINFO (expr));
- pph_out_tree (stream, BASELINK_FUNCTIONS (expr));
- pph_out_tree (stream, BASELINK_ACCESS_BINFO (expr));
- break;
-
- case TEMPLATE_INFO:
- pph_out_tree_common (stream, expr);
- pph_out_qual_use_vec (stream, TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (expr));
- break;
-
- case DEFAULT_ARG:
- pph_out_tree_common (stream, expr);
- pph_out_token_cache (stream, DEFARG_TOKENS (expr));
- pph_out_tree_vec (stream, DEFARG_INSTANTIATIONS (expr));
- break;
-
- case STATIC_ASSERT:
- pph_out_tree_common (stream, expr);
- pph_out_tree (stream, STATIC_ASSERT_CONDITION (expr));
- pph_out_tree (stream, STATIC_ASSERT_MESSAGE (expr));
- pph_out_location (stream, STATIC_ASSERT_SOURCE_LOCATION (expr));
- break;
-
- case ARGUMENT_PACK_SELECT:
- pph_out_tree_common (stream, expr);
- pph_out_tree (stream, ARGUMENT_PACK_SELECT_FROM_PACK (expr));
- pph_out_uint (stream, ARGUMENT_PACK_SELECT_INDEX (expr));
- break;
-
- case TRAIT_EXPR:
- pph_out_tree_common (stream, expr);
- pph_out_tree (stream, TRAIT_EXPR_TYPE1 (expr));
- pph_out_tree (stream, TRAIT_EXPR_TYPE2 (expr));
- pph_out_uint (stream, TRAIT_EXPR_KIND (expr));
- break;
-
- case LAMBDA_EXPR:
- pph_out_tree_common (stream, expr);
- pph_out_location (stream, LAMBDA_EXPR_LOCATION (expr));
- pph_out_tree (stream, LAMBDA_EXPR_CAPTURE_LIST (expr));
- pph_out_tree (stream, LAMBDA_EXPR_THIS_CAPTURE (expr));
- pph_out_tree (stream, LAMBDA_EXPR_RETURN_TYPE (expr));
- pph_out_tree (stream, LAMBDA_EXPR_EXTRA_SCOPE (expr));
- pph_out_uint (stream, LAMBDA_EXPR_DISCRIMINATOR (expr));
- break;
-
- case TREE_VEC:
- /* TREE_VECs hold template argument lists. */
- pph_out_tree (stream, NON_DEFAULT_TEMPLATE_ARGS_COUNT (expr));
- break;
-
- case PLACEHOLDER_EXPR:
- pph_out_tree (stream, TREE_TYPE (expr));
- break;
-
- case TEMPLATE_PARM_INDEX:
- pph_out_tree_common (stream, expr);
- pph_out_uint (stream, TEMPLATE_PARM_IDX (expr));
- pph_out_uint (stream, TEMPLATE_PARM_LEVEL (expr));
- pph_out_uint (stream, TEMPLATE_PARM_ORIG_LEVEL (expr));
- pph_out_uint (stream, TEMPLATE_PARM_NUM_SIBLINGS (expr));
- pph_out_tree (stream, TEMPLATE_PARM_DECL (expr));
- break;
-
- case DEFERRED_NOEXCEPT:
- pph_out_tree (stream, DEFERRED_NOEXCEPT_PATTERN (expr));
- pph_out_tree (stream, DEFERRED_NOEXCEPT_ARGS (expr));
- break;
-
- /* TREES ALREADY HANDLED */
- case ERROR_MARK:
- case TREE_LIST:
- case BLOCK:
- case CONSTRUCTOR:
- case SSA_NAME:
- case TREE_BINFO:
- break;
-
- /* TREES UNIMPLEMENTED */
- case OMP_CLAUSE:
- case OPTIMIZATION_NODE:
- case TARGET_OPTION_NODE:
- fatal_error ("PPH: unimplemented tree node '%s'",
- pph_tree_code_text (TREE_CODE (expr)));
- break;
-
- /* TREES UNRECOGNIZED */
- default:
- fatal_error ("PPH: unrecognized tree node '%s'",
- pph_tree_code_text (TREE_CODE (expr)));
- }
-}
-
-
-/* Pack all the bitfields of EXPR into BP. */
-
-static void
-pph_pack_value_fields (struct bitpack_d *bp, tree expr)
-{
- /* First pack all the language-independent bitfields. */
- streamer_pack_tree_bitfields (bp, expr);
-
- /* Now pack all the bitfields not handled by the generic packer. */
- if (TYPE_P (expr))
- {
- bp_pack_value (bp, TYPE_LANG_FLAG_0 (expr), 1);
- bp_pack_value (bp, TYPE_LANG_FLAG_1 (expr), 1);
- bp_pack_value (bp, TYPE_LANG_FLAG_2 (expr), 1);
- bp_pack_value (bp, TYPE_LANG_FLAG_3 (expr), 1);
- bp_pack_value (bp, TYPE_LANG_FLAG_4 (expr), 1);
- bp_pack_value (bp, TYPE_LANG_FLAG_5 (expr), 1);
- bp_pack_value (bp, TYPE_LANG_FLAG_6 (expr), 1);
- }
- else if (DECL_P (expr))
- {
- bp_pack_value (bp, DECL_LANG_FLAG_0 (expr), 1);
- bp_pack_value (bp, DECL_LANG_FLAG_1 (expr), 1);
- bp_pack_value (bp, DECL_LANG_FLAG_2 (expr), 1);
- bp_pack_value (bp, DECL_LANG_FLAG_3 (expr), 1);
- bp_pack_value (bp, DECL_LANG_FLAG_4 (expr), 1);
- bp_pack_value (bp, DECL_LANG_FLAG_5 (expr), 1);
- bp_pack_value (bp, DECL_LANG_FLAG_6 (expr), 1);
- bp_pack_value (bp, DECL_LANG_FLAG_7 (expr), 1);
- bp_pack_value (bp, DECL_LANG_FLAG_8 (expr), 1);
- }
-
- bp_pack_value (bp, TREE_LANG_FLAG_0 (expr), 1);
- bp_pack_value (bp, TREE_LANG_FLAG_1 (expr), 1);
- bp_pack_value (bp, TREE_LANG_FLAG_2 (expr), 1);
- bp_pack_value (bp, TREE_LANG_FLAG_3 (expr), 1);
- bp_pack_value (bp, TREE_LANG_FLAG_4 (expr), 1);
- bp_pack_value (bp, TREE_LANG_FLAG_5 (expr), 1);
- bp_pack_value (bp, TREE_LANG_FLAG_6 (expr), 1);
-}
-
-
-/* Write the header fields for EXPR to STREAM. This header contains
- all the data needed to rematerialize EXPR on the reader side and
- a bitpack with all the bitfield values in EXPR. */
-
-static void
-pph_out_tree_header (pph_stream *stream, tree expr)
-{
- struct bitpack_d bp;
- struct output_block *ob = stream->encoder.w.ob;
-
- /* Write the header, containing everything needed to materialize EXPR
- on the reading side. */
- streamer_write_tree_header (ob, expr);
-
- /* Process C++ specific codes that need more data in the header
- for the reader to allocate them. */
- if (TREE_CODE (expr) == AGGR_INIT_EXPR)
- pph_out_uint (stream, aggr_init_expr_nargs (expr));
-
- /* Pack all the non-pointer fields in EXPR into a bitpack and write
- the resulting bitpack. */
- bp = bitpack_create (ob->main_stream);
- pph_pack_value_fields (&bp, expr);
- pph_out_bitpack (stream, &bp);
-}
-
-
-/* Return the merge name string identifier tree for a decl EXPR. The
- caller is responsible of freeing the returned string. */
-
-static char *
-pph_merge_name (tree expr)
-{
- char *retval;
- size_t len;
- const char *mangled_str, *name_str;
- tree name;
-
- unsigned flags = TFF_PLAIN_IDENTIFIER
- | TFF_SCOPE
- | TFF_DECL_SPECIFIERS
- | TFF_CLASS_KEY_OR_ENUM
- | TFF_RETURN_TYPE;
-
- if (TYPE_P (expr))
- expr = TYPE_NAME (expr);
-
- name_str = decl_as_string (expr, flags);
-
- name = DECL_NAME (expr);
- if (name)
- {
- if (TREE_CODE (expr) == FUNCTION_DECL)
- flags |= TFF_RETURN_TYPE
- | TFF_FUNCTION_DEFAULT_ARGUMENTS
- | TFF_EXCEPTION_SPECIFICATION;
- else if (TREE_CODE (expr) == TEMPLATE_DECL)
- flags |= TFF_TEMPLATE_HEADER
- | TFF_NO_OMIT_DEFAULT_TEMPLATE_ARGUMENTS;
- mangled_str = IDENTIFIER_POINTER (get_mangled_id (expr));
- len = strlen (name_str) + sizeof("|") + strlen (mangled_str);
- retval = XNEWVEC (char, len + 1);
- sprintf (retval, "%s|%s", name_str, mangled_str);
- }
- else
- {
- location_t locus = DECL_SOURCE_LOCATION (expr);
- expanded_location xloc = expand_location (locus);
- /* There are at most 20 digits in size_t. Add :| for 22 characters. */
- len = strlen (name_str) + strlen (xloc.file) + 22;
- retval = XNEWVEC (char, len + 1);
- sprintf (retval, "%s|%s:%u", name_str, xloc.file, xloc.line);
- }
-
- return retval;
-}
-
-
-/* Write the merge name string for a decl EXPR. */
-
-static void
-pph_out_merge_name (pph_stream *stream, tree expr)
-{
- char *name = pph_merge_name (expr);
- pph_out_string (stream, name);
- free (name);
-}
-
-
-/* Write the merge key for tree EXPR to STREAM. */
-
-static void
-pph_out_merge_key_tree (pph_stream *stream, tree expr)
-{
- gcc_assert (pph_tree_is_mergeable (expr));
-
- if (pph_out_start_merge_key_record (stream, expr))
- return;
-
- if (flag_pph_tracer)
- pph_trace_tree (expr, pph_trace_front, pph_trace_key_out);
-
- /* Write merge key information. This includes EXPR's header (needed
- to re-allocate EXPR in the reader) and the merge key, used to
- lookup EXPR in the reader's context and merge if necessary. */
- pph_out_tree_header (stream, expr);
- pph_out_merge_name (stream, expr);
- if (DECL_P (expr))
- {
- if (TREE_CODE (expr) == NAMESPACE_DECL)
- pph_out_binding_merge_keys (stream, NAMESPACE_LEVEL (expr));
-#if 0
-/* FIXME pph: Distable tree merging for the moment. */
- else if (TREE_CODE (expr) == TYPE_DECL)
- pph_out_merge_key_tree (stream, TREE_TYPE (expr));
- }
- else if (CLASS_TYPE_P (expr))
- {
- unsigned filter = PPHF_NO_XREFS | PPHF_NO_PREFS | PPHF_NO_BUILTINS;
- pph_out_merge_key_chain (stream, TYPE_FIELDS (expr), filter);
- pph_out_merge_key_chain (stream, TYPE_METHODS (expr), filter);
- /* FIXME pph: Nested types are broken.
- pph_out_binding_table (stream, CLASSTYPE_NESTED_UTDS (expr));
- pph_out_merge_key_chain (stream, CLASSTYPE_DECL_LIST (expr), filter);
- */
-#endif
- }
-
- if (flag_pph_tracer)
- pph_trace_tree (expr, pph_trace_back, pph_trace_key_out);
-}
-
-
-/* Write a tree EXPR to STREAM. */
-
-void
-pph_out_tree (pph_stream *stream, tree expr)
-{
- enum pph_record_marker marker;
-
- marker = pph_out_start_tree_record (stream, expr);
-
- /* If EXPR is NULL or it already existed in the pickle cache,
- nothing else needs to be done. */
- if (marker == PPH_RECORD_END || pph_is_reference_marker (marker))
- return;
-
- if (streamer_handle_as_builtin_p (expr))
- {
- /* MD and NORMAL builtins do not need to be written out
- completely as they are always instantiated by the compiler on
- startup. The only builtins that need to be written out are
- BUILT_IN_FRONTEND. For all other builtins, we simply write
- the class and code. */
- gcc_assert (marker == PPH_RECORD_START_NO_CACHE);
- streamer_write_builtin (stream->encoder.w.ob, expr);
- return;
- }
- else if (TREE_CODE (expr) == INTEGER_CST)
- {
- /* INTEGER_CST nodes are special because they need their
- original type to be materialized by the reader (to implement
- TYPE_CACHED_VALUES). */
- gcc_assert (marker == PPH_RECORD_START_NO_CACHE);
- streamer_write_integer_cst (stream->encoder.w.ob, expr, false);
- return;
- }
-
- if (flag_pph_tracer)
- pph_trace_tree (expr, pph_trace_front,
- marker == PPH_RECORD_START_MERGE_BODY ? pph_trace_merge_body
- : marker == PPH_RECORD_START_MUTATED ? pph_trace_mutate
- : pph_trace_normal);
-
- if (marker == PPH_RECORD_START || marker == PPH_RECORD_START_MUTATED)
- {
-
- /* This is the first time we see EXPR, write it out. */
- if (marker == PPH_RECORD_START)
- {
- /* We only need to write EXPR's header if it needs to be
- re-allocated when reading. If we are writing the mutated
- state of an existing tree, then we only need to write its
- body. */
- pph_out_tree_header (stream, expr);
- }
-
- pph_out_tree_body (stream, expr);
- }
- else if (marker == PPH_RECORD_START_MERGE_BODY)
- {
- gcc_assert (pph_tree_is_mergeable (expr));
-
- /* When writing a merge body, we do not need to write EXPR's
- header, since that was written out when we wrote the merge
- key record for it. */
- pph_out_tree_body (stream, expr);
- }
- else
- gcc_unreachable ();
-
- if (flag_pph_tracer)
- pph_trace_tree (expr, pph_trace_back,
- marker == PPH_RECORD_START_MERGE_BODY ? pph_trace_merge_body
- : marker == PPH_RECORD_START_MUTATED ? pph_trace_mutate
- : pph_trace_normal);
-}
-
-
-/************************************************************* file contents */
-
-
-/* Emit symbol table ACTION to STREAM. */
-
-static inline void
-pph_out_symtab_action (pph_stream *stream, enum pph_symtab_action action)
-{
- gcc_assert (action == (enum pph_symtab_action)(unsigned char) action);
- pph_out_uchar (stream, action);
-}
-
-
-/* Emit callgraph NODE to STREAM. */
-
-static void
-pph_out_cgraph_node (pph_stream *stream, struct cgraph_node *node)
-{
- struct bitpack_d bp;
-
- if (pph_out_start_record (stream, node, PPH_cgraph_node))
- return;
-
- pph_out_tree (stream, node->decl);
- pph_out_cgraph_node (stream, node->origin);
- pph_out_cgraph_node (stream, node->nested);
- pph_out_cgraph_node (stream, node->next_nested);
- pph_out_cgraph_node (stream, node->next_needed);
- pph_out_cgraph_node (stream, node->next_sibling_clone);
- pph_out_cgraph_node (stream, node->prev_sibling_clone);
- pph_out_cgraph_node (stream, node->clones);
- pph_out_cgraph_node (stream, node->clone_of);
- pph_out_cgraph_node (stream, node->same_comdat_group);
- gcc_assert (node->call_site_hash == NULL);
- pph_out_tree (stream, node->former_clone_of);
- gcc_assert (node->aux == NULL);
- gcc_assert (VEC_empty (ipa_opt_pass, node->ipa_transforms_to_apply));
-
- gcc_assert (VEC_empty (ipa_ref_t, node->ref_list.references));
- gcc_assert (VEC_empty (ipa_ref_ptr, node->ref_list.refering));
-
- gcc_assert (node->local.lto_file_data == NULL);
- bp = bitpack_create (stream->encoder.w.ob->main_stream);
- bp_pack_value (&bp, node->local.local, 1);
- bp_pack_value (&bp, node->local.externally_visible, 1);
- bp_pack_value (&bp, node->local.finalized, 1);
- bp_pack_value (&bp, node->local.can_change_signature, 1);
- bp_pack_value (&bp, node->local.redefined_extern_inline, 1);
- pph_out_bitpack (stream, &bp);
-
- pph_out_cgraph_node (stream, node->global.inlined_to);
-
- pph_out_uint (stream, node->rtl.preferred_incoming_stack_boundary);
-
- gcc_assert (VEC_empty (ipa_replace_map_p, node->clone.tree_map));
- pph_out_uhwi (stream, node->thunk.fixed_offset);
- pph_out_uhwi (stream, node->thunk.virtual_value);
- pph_out_tree (stream, node->thunk.alias);
- bp = bitpack_create (stream->encoder.w.ob->main_stream);
- bp_pack_value (&bp, node->thunk.this_adjusting, 1);
- bp_pack_value (&bp, node->thunk.virtual_offset_p, 1);
- bp_pack_value (&bp, node->thunk.thunk_p, 1);
- pph_out_bitpack (stream, &bp);
-
- pph_out_uhwi (stream, node->count);
- pph_out_uint (stream, node->count_materialization_scale);
-
- bp = bitpack_create (stream->encoder.w.ob->main_stream);
- bp_pack_value (&bp, node->needed, 1);
- bp_pack_value (&bp, node->address_taken, 1);
- bp_pack_value (&bp, node->abstract_and_needed, 1);
- bp_pack_value (&bp, node->reachable, 1);
- bp_pack_value (&bp, node->reachable_from_other_partition, 1);
- bp_pack_value (&bp, node->lowered, 1);
- bp_pack_value (&bp, node->analyzed, 1);
- bp_pack_value (&bp, node->in_other_partition, 1);
- bp_pack_value (&bp, node->process, 1);
- bp_pack_value (&bp, node->alias, 1);
- bp_pack_value (&bp, node->same_body_alias, 1);
- bp_pack_value (&bp, node->frequency, 2);
- bp_pack_value (&bp, node->only_called_at_startup, 1);
- bp_pack_value (&bp, node->only_called_at_exit, 1);
- pph_out_bitpack (stream, &bp);
-}
-
-
-/* Add DECL to the symbol table for pph_out_stream. ACTION determines
- how DECL should be presented to the middle-end when reading this
- image. TOP_LEVEL and AT_END are as in rest_of_decl_compilation. */
-
-void
-pph_add_decl_to_symtab (tree decl, enum pph_symtab_action action,
- bool top_level, bool at_end)
-{
- pph_symtab_entry entry;
-
- if (decl == NULL || pph_out_stream == NULL)
- return;
-
- gcc_assert (DECL_P (decl));
-
- entry.action = action;
- entry.decl = decl;
- entry.top_level = top_level;
- entry.at_end = at_end;
- VEC_safe_push (pph_symtab_entry, heap, pph_out_stream->symtab.v, &entry);
-}
-
-
-/* Emit the symbol table for STREAM. When this image is read into
- another translation unit, we want to guarantee that the IL
- instances taken from this image are instantiated in the same order
- that they were instantiated when we generated this image.
-
- With this, we can generate code in the same order out of the
- original header files and out of PPH images. */
-
-static void
-pph_out_symtab (pph_stream *stream)
-{
- pph_symtab_entry *entry;
- unsigned i;
-
- pph_out_uint (stream, VEC_length (pph_symtab_entry, stream->symtab.v));
- FOR_EACH_VEC_ELT (pph_symtab_entry, stream->symtab.v, i, entry)
- {
- pph_out_symtab_action (stream, entry->action);
- pph_out_tree (stream, entry->decl);
- if (entry->action == PPH_SYMTAB_DECLARE)
- {
- struct bitpack_d bp;
- bp = bitpack_create (stream->encoder.w.ob->main_stream);
- bp_pack_value (&bp, entry->top_level, 1);
- bp_pack_value (&bp, entry->at_end, 1);
- pph_out_bitpack (stream, &bp);
- }
- else if (entry->action == PPH_SYMTAB_EXPAND)
- {
- pph_out_struct_function (stream, DECL_STRUCT_FUNCTION (entry->decl));
- pph_out_cgraph_node (stream, cgraph_get_node (entry->decl));
- }
- else
- gcc_unreachable ();
- }
-}
-
-
-/* Save the IDENTIFIERS to the STREAM. */
-
-static void
-pph_out_identifiers (pph_stream *stream, cpp_idents_used *identifiers)
-{
- unsigned int num_entries, active_entries, id;
-
- num_entries = identifiers->num_entries;
- pph_out_uint (stream, identifiers->max_ident_len);
- pph_out_uint (stream, identifiers->max_value_len);
-
- active_entries = 0;
- for ( id = 0; id < num_entries; ++id )
- {
- cpp_ident_use *entry = identifiers->entries + id;
- if (!(entry->used_by_directive || entry->expanded_to_text))
- continue;
- ++active_entries;
- }
-
- pph_out_uint (stream, active_entries);
-
- for ( id = 0; id < num_entries; ++id )
- {
- cpp_ident_use *entry = identifiers->entries + id;
-
- if (!(entry->used_by_directive || entry->expanded_to_text))
- continue;
-
- /* FIXME pph: We are wasting space; ident_len, used_by_directive
- and expanded_to_text together could fit into a single uint. */
-
- pph_out_uint (stream, entry->used_by_directive);
- pph_out_uint (stream, entry->expanded_to_text);
-
- gcc_assert (entry->ident_len <= identifiers->max_ident_len);
- pph_out_string_with_length (stream, entry->ident_str,
- entry->ident_len);
-
- gcc_assert (entry->before_len <= identifiers->max_value_len);
- pph_out_string_with_length (stream, entry->before_str,
- entry->before_len);
-
- gcc_assert (entry->after_len <= identifiers->max_value_len);
- pph_out_string_with_length (stream, entry->after_str,
- entry->after_len);
- }
-}
-
-
-/* Write the global bindings in scope_chain to STREAM. */
-
-static void
-pph_out_global_binding (pph_stream *stream)
-{
- cp_binding_level *bl;
-
- /* We only need to write out the scope_chain->bindings, everything
- else should be NULL or be some temporary disposable state.
- old_namespace should be global_namespace and all entries listed
- below should be NULL or 0; otherwise the header parsed was
- incomplete. */
- gcc_assert (scope_chain->old_namespace == global_namespace
- && !(scope_chain->class_name
- || scope_chain->class_type
- || scope_chain->access_specifier
- || scope_chain->function_decl
- || scope_chain->template_parms
- || scope_chain->x_saved_tree
- || scope_chain->class_bindings
- || scope_chain->prev
- || scope_chain->unevaluated_operand
- || scope_chain->inhibit_evaluation_warnings
- || scope_chain->x_processing_template_decl
- || scope_chain->x_processing_specialization
- || scope_chain->x_processing_explicit_instantiation
- || scope_chain->need_pop_function_context
- || scope_chain->x_stmt_tree.x_cur_stmt_list
- || scope_chain->x_stmt_tree.stmts_are_full_exprs_p));
-
- /* We need to write a record for BL before emitting the merge keys
- so that the reader can associate the merge keys to it. */
- bl = scope_chain->bindings;
- pph_out_start_record (stream, bl, PPH_cp_binding_level);
-
- /* Emit all the merge keys for objects that need to be merged when reading
- multiple PPH images. */
- pph_out_binding_merge_keys (stream, bl);
- pph_out_binding_merge_bodies (stream, bl);
-}
-
-
-/* Write all the contents of STREAM. */
-
-static void
-pph_write_file (pph_stream *stream)
-{
- cpp_idents_used idents_used;
-
- if (flag_pph_tracer >= 1)
- fprintf (pph_logfile, "PPH: Writing %s\n", pph_out_file);
-
- /* Emit the line table entries and references to our direct includes. */
- pph_out_line_table_and_includes (stream);
-
- /* Emit all the identifiers and pre-processor symbols in the global
- namespace. */
- idents_used = cpp_lt_capture (parse_in);
- pph_out_identifiers (stream, &idents_used);
-
- /* Emit the bindings for the global namespace. */
- pph_out_global_binding (stream);
-
- /* Emit other global state kept by the parser. FIXME pph, these
- globals should be fields in struct cp_parser. */
- pph_out_tree (stream, keyed_classes);
- pph_out_tree_vec (stream, unemitted_tinfo_decls);
-
- pph_out_pending_templates_list (stream);
- pph_out_spec_entry_tables (stream);
-
- pph_out_tree (stream, static_aggregates);
-
- /* Emit the symbol table. */
- pph_out_symtab (stream);
-
- if (flag_pph_dump_tree)
- pph_dump_namespace (pph_logfile, global_namespace);
-}
-
-
-/******************************************************* stream finalization */
-
-
-/* Callback for lang_hooks.lto.begin_section. Open file NAME. */
-
-static void
-pph_begin_section (const char *name ATTRIBUTE_UNUSED)
-{
-}
-
-
-/* Callback for lang_hooks.lto.append_data. Write LEN bytes from DATA
- into pph_out_stream. BLOCK is currently unused. */
-
-static void
-pph_out_data (const void *data, size_t len, void *block ATTRIBUTE_UNUSED)
-{
- if (data)
- {
- size_t written = fwrite (data, 1, len, pph_out_stream->file);
- gcc_assert (written == len);
- }
-}
-
-
-/* Callback for lang_hooks.lto.end_section. */
-
-static void
-pph_end_section (void)
-{
-}
-
-/* Write the header for the PPH file represented by STREAM. */
-
-static void
-pph_out_header (pph_stream *stream)
-{
- pph_file_header header;
- struct lto_output_stream header_stream;
- int major, minor, patchlevel;
-
- /* Collect version information. */
- parse_basever (&major, &minor, &patchlevel);
- gcc_assert (major == (char) major);
- gcc_assert (minor == (char) minor);
- gcc_assert (patchlevel == (char) patchlevel);
-
- /* Write the header for the PPH file. */
- memset (&header, 0, sizeof (header));
- strcpy (header.id_str, pph_id_str);
- header.major_version = (char) major;
- header.minor_version = (char) minor;
- header.patchlevel = (char) patchlevel;
- header.strtab_size = stream->encoder.w.ob->string_stream->total_size;
-
- memset (&header_stream, 0, sizeof (header_stream));
- lto_output_data_stream (&header_stream, &header, sizeof (header));
- lto_write_stream (&header_stream);
-}
-
-
-/* Write the body of the PPH file represented by STREAM. */
-
-static void
-pph_out_body (pph_stream *stream)
-{
- /* Write the string table. */
- lto_write_stream (stream->encoder.w.ob->string_stream);
-
- /* Write the main stream where we have been pickling the parse trees. */
- lto_write_stream (stream->encoder.w.ob->main_stream);
-}
-
-
-/* Flush all the in-memory buffers for STREAM to disk. */
-
-void
-pph_flush_buffers (pph_stream *stream)
-{
- /* Redirect the LTO basic I/O langhooks. */
- lang_hooks.lto.begin_section = pph_begin_section;
- lang_hooks.lto.append_data = pph_out_data;
- lang_hooks.lto.end_section = pph_end_section;
-
- /* Write the state buffers built by pph_out_*() calls. */
- lto_begin_section (stream->name, false);
- pph_out_header (stream);
- pph_out_body (stream);
- lto_end_section ();
-}
-
-
-/* Finalize the PPH writer. */
-
-void
-pph_writer_finish (void)
-{
- const char *offending_file;
-
- if (pph_out_stream == NULL)
- return;
-
- offending_file = cpp_main_missing_guard (parse_in);
- if (offending_file == NULL)
- pph_write_file (pph_out_stream);
- else
- error ("header lacks guard for PPH: %s", offending_file);
-
- pph_stream_close (pph_out_stream);
- pph_out_stream = NULL;
-}
-
-
-/* Add INCLUDE to the list of images included by pph_out_stream. */
-
-void
-pph_writer_add_include (pph_stream *include)
-{
- pph_add_include (pph_out_stream, include);
-}
Index: gcc/cp/pph-streamer.h
===================================================================
--- gcc/cp/pph-streamer.h (revision 181815)
+++ gcc/cp/pph-streamer.h (working copy)
@@ -226,13 +226,6 @@ struct pph_stream {
#define PPHF_NO_XREFS (1 << 1)
#define PPHF_NO_PREFS (1 << 2)
-/* In pph.c */
-extern const char *pph_tree_code_text (enum tree_code code);
-extern void pph_dump_min_decl (FILE *file, tree decl);
-extern void pph_dump_chain (FILE *, tree chain);
-extern void pph_dump_binding (FILE *, cp_binding_level *level);
-extern void pph_dump_namespace (FILE *, tree ns);
-
enum pph_trace_kind
{
pph_trace_key_out, pph_trace_unmerged_key, pph_trace_merged_key,
@@ -244,9 +237,9 @@ enum pph_trace_end
pph_trace_front, pph_trace_back
};
-/* In pph-streamer.c. */
-void pph_streamer_init (void);
-void pph_streamer_finish (void);
+/* In pph-core.c. */
+const char *pph_tree_code_text (enum tree_code code);
+void pph_dump_namespace (FILE *, tree ns);
pph_stream *pph_stream_open (const char *, const char *);
void pph_mark_stream_read (pph_stream *);
void pph_stream_close (pph_stream *);
@@ -265,7 +258,7 @@ void pph_cache_sign (pph_cache *, unsign
unsigned pph_get_signature (tree, size_t *);
void pph_writer_add_include (pph_stream *);
-/* In pph-streamer-out.c. */
+/* In pph-out.c. */
void pph_flush_buffers (pph_stream *);
void pph_init_write (pph_stream *);
void pph_write_mergeable_chain (pph_stream *, tree);
@@ -274,7 +267,7 @@ void pph_writer_finish (void);
void pph_out_location (pph_stream *, location_t);
void pph_out_tree (pph_stream *, tree);
-/* In pph-streamer-in.c. */
+/* In pph-in.c. */
void pph_init_read (pph_stream *);
location_t pph_in_location (pph_stream *);
pph_stream *pph_read_file (const char *);
--
This patch is available for review at http://codereview.appspot.com/5440063