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)
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/>. */
23 #include "coretypes.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"
31 #include "tree-pass.h"
33 #include "cppbuiltin.h"
35 /* Return true if the given tree T is streamable. */
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. */
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)
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
++)
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
]);
88 /* Initialize all the streamer hooks used for streaming ASTs. */
91 pph_stream_hooks_init (void)
93 lto_streamer_hooks
*h
= streamer_hooks_init ();
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. */
112 pph_stream_open (const char *name
, const char *mode
)
118 f
= fopen (name
, mode
);
121 pph_stream_hooks_init ();
122 stream
= XCNEW (pph_stream
);
124 stream
->name
= xstrdup (name
);
125 stream
->write_p
= (strchr (mode
, 'w') != NULL
);
127 pph_stream_init_write (stream
);
129 pph_stream_init_read (stream
);
130 stream
->cache
.v
= NULL
;
131 stream
->cache
.m
= pointer_map_create ();
138 /* Close PPH stream STREAM. Write all the ASTs to disk and deallocate
139 all memory used by it. */
142 pph_stream_close (pph_stream
*stream
)
145 pph_stream_flush_buffers (stream
);
146 fclose (stream
->file
);
148 VEC_free (void_p
, heap
, stream
->cache
.v
);
149 pointer_map_destroy (stream
->cache
.m
);
154 /* Data types supported by the PPH tracer. */
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. */
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",
179 if ((type
== PPH_TRACE_TREE
|| type
== PPH_TRACE_CHAIN
)
181 && flag_pph_tracer
<= 3)
184 fprintf (pph_logfile
, "*** %s: %s%s/%u, value=",
185 stream
->name
, op
, type_s
[type
], (unsigned) nbytes
);
191 const_tree t
= (const_tree
) data
;
194 print_generic_expr (pph_logfile
, CONST_CAST (union tree_node
*, t
),
196 fprintf (pph_logfile
, ", code=%s", tree_code_name
[TREE_CODE (t
)]);
199 fprintf (pph_logfile
, "NULL_TREE");
205 const_tree t
= (const_tree
) data
;
208 print_generic_expr (pph_logfile
, CONST_CAST (union tree_node
*, t
),
210 fprintf (pph_logfile
, ", code=%s", tree_code_name
[TREE_CODE (t
)]);
213 fprintf (pph_logfile
, "NULL_TREE");
219 unsigned int val
= *((const unsigned int *) data
);
220 fprintf (pph_logfile
, "%u (0x%x)", val
, val
);
224 case PPH_TRACE_BYTES
:
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
]);
233 fprintf (pph_logfile
, "[0x%02x]", (unsigned int) buffer
[i
]);
238 case PPH_TRACE_STRING
:
240 fprintf (pph_logfile
, "%.*s", (int) nbytes
, (const char *) data
);
242 fprintf (pph_logfile
, "<nil>");
245 case PPH_TRACE_CHAIN
:
247 const_tree t
= (const_tree
) data
;
248 print_generic_expr (pph_logfile
, CONST_CAST (union tree_node
*, t
),
250 fprintf (pph_logfile
, " (%d nodes in chain)", list_length (t
));
254 case PPH_TRACE_BITPACK
:
256 const struct bitpack_d
*bp
= (const struct bitpack_d
*) data
;
257 fprintf (pph_logfile
, "0x%lx", bp
->word
);
265 fputc ('\n', pph_logfile
);
269 /* Show tracing information for T on STREAM. */
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. */
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
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. */
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. */
310 pph_stream_trace_string_with_length (pph_stream
*stream
, const char *s
,
313 pph_stream_trace (stream
, s
, len
, PPH_TRACE_STRING
);
317 /* Show tracing information for a tree chain starting with T on STREAM. */
320 pph_stream_trace_chain (pph_stream
*stream
, tree t
)
322 pph_stream_trace (stream
, t
, t
? tree_code_size (TREE_CODE (t
)) : 0,
327 /* Show tracing information for a bitpack BP on STREAM. */
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. */
340 pph_stream_cache_insert_at (pph_stream
*stream
, void *data
, unsigned ix
)
344 map_slot
= pointer_map_insert (stream
->cache
.m
, data
);
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
350 unsigned HOST_WIDE_INT prev_ix
= (unsigned HOST_WIDE_INT
) *map_slot
;
351 gcc_assert (prev_ix
== ix
);
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. */
368 pph_stream_cache_add (pph_stream
*stream
, void *data
, unsigned *ix_p
)
374 map_slot
= pointer_map_contains (stream
->cache
.m
, data
);
375 if (map_slot
== NULL
)
378 ix
= VEC_length (void_p
, stream
->cache
.v
);
379 pph_stream_cache_insert_at (stream
, data
, ix
);
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
;
395 /* Return the pointer at slot IX in STREAM's pickle cache. */
398 pph_stream_cache_get (pph_stream
*stream
, unsigned ix
)
400 void *data
= VEC_index (void_p
, stream
->cache
.v
, ix
);