2011-05-27 Diego Novillo <dnovillo@google.com>
[official-gcc.git] / gcc / cp / pph-streamer.c
bloba00a243fd86f449ad5194c0a367e13c82d9fae89
1 /* Routines for streaming PPH data.
2 Copyright (C) 2011 Free Software Foundation, Inc.
3 Contributed by Diego Novillo <dnovillo@google.com>.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
12 GCC is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tree.h"
25 #include "langhooks.h"
26 #include "tree-iterator.h"
27 #include "tree-pretty-print.h"
28 #include "lto-streamer.h"
29 #include "pph-streamer.h"
30 #include "pph.h"
31 #include "tree-pass.h"
32 #include "version.h"
33 #include "cppbuiltin.h"
35 /* Return true if the given tree T is streamable. */
37 static bool
38 pph_is_streamable (tree t ATTRIBUTE_UNUSED)
40 /* We accept most trees. */
41 return TREE_CODE (t) != SSA_NAME
42 && (TREE_CODE (t) < OMP_PARALLEL
43 || TREE_CODE (t) > OMP_CRITICAL);
47 /* Return true if T can be emitted in the decls table as a reference.
48 This should only handle C++ specific declarations. All others are
49 handled by the LTO streamer directly. */
51 static bool
52 pph_indexable_with_decls_p (tree t)
54 return TREE_CODE (t) == TEMPLATE_DECL;
58 /* Generate a vector of common nodes that should always be streamed as
59 indexes into the streamer cache. These nodes are always built by
60 the front end, so there is no need to emit them. */
62 static VEC(tree,heap) *
63 pph_get_common_nodes (void)
65 unsigned i;
66 VEC(tree,heap) *common_nodes = NULL;
68 for (i = itk_char; i < itk_none; i++)
69 VEC_safe_push (tree, heap, common_nodes, integer_types[i]);
71 for (i = 0; i < TYPE_KIND_LAST; i++)
72 VEC_safe_push (tree, heap, common_nodes, sizetype_tab[i]);
74 /* global_trees[] can have NULL entries in it. Skip them. */
75 for (i = 0; i < TI_MAX; i++)
76 if (global_trees[i])
77 VEC_safe_push (tree, heap, common_nodes, global_trees[i]);
79 /* c_global_trees[] can have NULL entries in it. Skip them. */
80 for (i = 0; i < CTI_MAX; i++)
81 if (c_global_trees[i])
82 VEC_safe_push (tree, heap, common_nodes, c_global_trees[i]);
84 return common_nodes;
88 /* Initialize all the streamer hooks used for streaming ASTs. */
90 static void
91 pph_stream_hooks_init (void)
93 lto_streamer_hooks *h = streamer_hooks_init ();
94 h->name = "C++ AST";
95 h->get_common_nodes = pph_get_common_nodes;
96 h->is_streamable = pph_is_streamable;
97 h->write_tree = pph_stream_write_tree;
98 h->read_tree = pph_stream_read_tree;
99 h->pack_value_fields = pph_stream_pack_value_fields;
100 h->indexable_with_decls_p = pph_indexable_with_decls_p;
101 h->unpack_value_fields = pph_stream_unpack_value_fields;
102 h->alloc_tree = pph_stream_alloc_tree;
103 h->output_tree_header = pph_stream_output_tree_header;
104 h->has_unique_integer_csts_p = true;
108 /* Create a new PPH stream to be stored on the file called NAME.
109 MODE is passed to fopen directly. */
111 pph_stream *
112 pph_stream_open (const char *name, const char *mode)
114 pph_stream *stream;
115 FILE *f;
117 stream = NULL;
118 f = fopen (name, mode);
119 if (f)
121 pph_stream_hooks_init ();
122 stream = XCNEW (pph_stream);
123 stream->file = f;
124 stream->name = xstrdup (name);
125 stream->write_p = (strchr (mode, 'w') != NULL);
126 if (stream->write_p)
127 pph_stream_init_write (stream);
128 else
129 pph_stream_init_read (stream);
130 stream->cache.v = NULL;
131 stream->cache.m = pointer_map_create ();
134 return stream;
138 /* Close PPH stream STREAM. Write all the ASTs to disk and deallocate
139 all memory used by it. */
141 void
142 pph_stream_close (pph_stream *stream)
144 if (stream->write_p)
145 pph_stream_flush_buffers (stream);
146 fclose (stream->file);
147 stream->file = NULL;
148 VEC_free (void_p, heap, stream->cache.v);
149 pointer_map_destroy (stream->cache.m);
150 free (stream);
154 /* Data types supported by the PPH tracer. */
155 enum pph_trace_type
157 PPH_TRACE_TREE,
158 PPH_TRACE_REF,
159 PPH_TRACE_UINT,
160 PPH_TRACE_BYTES,
161 PPH_TRACE_STRING,
162 PPH_TRACE_CHAIN,
163 PPH_TRACE_BITPACK
167 /* Print tracing information for STREAM on pph_logfile. DATA is the
168 memory area to display, SIZE is the number of bytes to print, TYPE
169 is the kind of data to print. */
171 static void
172 pph_stream_trace (pph_stream *stream, const void *data, unsigned int nbytes,
173 enum pph_trace_type type)
175 const char *op = (stream->write_p) ? "<<" : ">>";
176 const char *type_s[] = { "tree", "ref", "uint", "bytes", "string", "chain",
177 "bitpack" };
179 if ((type == PPH_TRACE_TREE || type == PPH_TRACE_CHAIN)
180 && !data
181 && flag_pph_tracer <= 3)
182 return;
184 fprintf (pph_logfile, "*** %s: %s%s/%u, value=",
185 stream->name, op, type_s[type], (unsigned) nbytes);
187 switch (type)
189 case PPH_TRACE_TREE:
191 const_tree t = (const_tree) data;
192 if (t)
194 print_generic_expr (pph_logfile, CONST_CAST (union tree_node *, t),
196 fprintf (pph_logfile, ", code=%s", tree_code_name[TREE_CODE (t)]);
198 else
199 fprintf (pph_logfile, "NULL_TREE");
201 break;
203 case PPH_TRACE_REF:
205 const_tree t = (const_tree) data;
206 if (t)
208 print_generic_expr (pph_logfile, CONST_CAST (union tree_node *, t),
210 fprintf (pph_logfile, ", code=%s", tree_code_name[TREE_CODE (t)]);
212 else
213 fprintf (pph_logfile, "NULL_TREE");
215 break;
217 case PPH_TRACE_UINT:
219 unsigned int val = *((const unsigned int *) data);
220 fprintf (pph_logfile, "%u (0x%x)", val, val);
222 break;
224 case PPH_TRACE_BYTES:
226 size_t i;
227 const char *buffer = (const char *) data;
228 for (i = 0; i < MIN (nbytes, 100); i++)
230 if (ISPRINT (buffer[i]))
231 fprintf (pph_logfile, "%c", buffer[i]);
232 else
233 fprintf (pph_logfile, "[0x%02x]", (unsigned int) buffer[i]);
236 break;
238 case PPH_TRACE_STRING:
239 if (data)
240 fprintf (pph_logfile, "%.*s", (int) nbytes, (const char *) data);
241 else
242 fprintf (pph_logfile, "<nil>");
243 break;
245 case PPH_TRACE_CHAIN:
247 const_tree t = (const_tree) data;
248 print_generic_expr (pph_logfile, CONST_CAST (union tree_node *, t),
249 TDF_SLIM);
250 fprintf (pph_logfile, " (%d nodes in chain)", list_length (t));
252 break;
254 case PPH_TRACE_BITPACK:
256 const struct bitpack_d *bp = (const struct bitpack_d *) data;
257 fprintf (pph_logfile, "0x%lx", bp->word);
259 break;
261 default:
262 gcc_unreachable ();
265 fputc ('\n', pph_logfile);
269 /* Show tracing information for T on STREAM. */
271 void
272 pph_stream_trace_tree (pph_stream *stream, tree t, bool ref_p)
274 pph_stream_trace (stream, t, t ? tree_code_size (TREE_CODE (t)) : 0,
275 ref_p ? PPH_TRACE_REF : PPH_TRACE_TREE);
279 /* Show tracing information for VAL on STREAM. */
281 void
282 pph_stream_trace_uint (pph_stream *stream, unsigned int val)
284 pph_stream_trace (stream, &val, sizeof (val), PPH_TRACE_UINT);
288 /* Show tracing information for NBYTES bytes of memory area DATA on
289 STREAM. */
291 void
292 pph_stream_trace_bytes (pph_stream *stream, const void *data, size_t nbytes)
294 pph_stream_trace (stream, data, nbytes, PPH_TRACE_BYTES);
298 /* Show tracing information for S on STREAM. */
300 void
301 pph_stream_trace_string (pph_stream *stream, const char *s)
303 pph_stream_trace (stream, s, s ? strlen (s) : 0, PPH_TRACE_STRING);
307 /* Show tracing information for LEN bytes of S on STREAM. */
309 void
310 pph_stream_trace_string_with_length (pph_stream *stream, const char *s,
311 unsigned int len)
313 pph_stream_trace (stream, s, len, PPH_TRACE_STRING);
317 /* Show tracing information for a tree chain starting with T on STREAM. */
319 void
320 pph_stream_trace_chain (pph_stream *stream, tree t)
322 pph_stream_trace (stream, t, t ? tree_code_size (TREE_CODE (t)) : 0,
323 PPH_TRACE_CHAIN);
327 /* Show tracing information for a bitpack BP on STREAM. */
329 void
330 pph_stream_trace_bitpack (pph_stream *stream, struct bitpack_d *bp)
332 pph_stream_trace (stream, bp, sizeof (*bp), PPH_TRACE_BITPACK);
336 /* Insert DATA in STREAM's pickle cache at slot IX. If DATA already
337 existed in the cache, IX must be the same as the previous entry. */
339 void
340 pph_stream_cache_insert_at (pph_stream *stream, void *data, unsigned ix)
342 void **map_slot;
344 map_slot = pointer_map_insert (stream->cache.m, data);
345 if (*map_slot)
347 /* DATA already existed in the cache. Do nothing, but check
348 that we are trying to insert DATA in the same slot that we
349 had it in before. */
350 unsigned HOST_WIDE_INT prev_ix = (unsigned HOST_WIDE_INT) *map_slot;
351 gcc_assert (prev_ix == ix);
353 else
355 *map_slot = (void *) (unsigned HOST_WIDE_INT) ix;
356 if (ix + 1 > VEC_length (void_p, stream->cache.v))
357 VEC_safe_grow_cleared (void_p, heap, stream->cache.v, ix + 1);
358 VEC_replace (void_p, stream->cache.v, ix, data);
363 /* Add pointer DATA to the pickle cache in STREAM. On exit, *IX_P will
364 contain the slot number where DATA is stored. Return true if DATA
365 already existed in the cache, false otherwise. */
367 bool
368 pph_stream_cache_add (pph_stream *stream, void *data, unsigned *ix_p)
370 void **map_slot;
371 unsigned ix;
372 bool existed_p;
374 map_slot = pointer_map_contains (stream->cache.m, data);
375 if (map_slot == NULL)
377 existed_p = false;
378 ix = VEC_length (void_p, stream->cache.v);
379 pph_stream_cache_insert_at (stream, data, ix);
381 else
383 unsigned HOST_WIDE_INT slot_ix = (unsigned HOST_WIDE_INT) *map_slot;
384 gcc_assert (slot_ix == (unsigned) slot_ix);
385 ix = (unsigned) slot_ix;
386 existed_p = true;
389 *ix_p = ix;
391 return existed_p;
395 /* Return the pointer at slot IX in STREAM's pickle cache. */
397 void *
398 pph_stream_cache_get (pph_stream *stream, unsigned ix)
400 void *data = VEC_index (void_p, stream->cache.v, ix);
401 gcc_assert (data);
403 return data;