* df-scan.c (df_collection_rec): Adjust.
[official-gcc.git] / gcc / tree-streamer.c
blob55c9ad571f677bbe71891f4bd777bfca9722b1e3
1 /* Miscellaneous utilities for tree streaming. Things that are used
2 in both input and output are here.
4 Copyright (C) 2011-2013 Free Software Foundation, Inc.
5 Contributed by Diego Novillo <dnovillo@google.com>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tree.h"
27 #include "streamer-hooks.h"
28 #include "tree-streamer.h"
30 /* Check that all the TS_* structures handled by the streamer_write_* and
31 streamer_read_* routines are exactly ALL the structures defined in
32 treestruct.def. */
34 void
35 streamer_check_handled_ts_structures (void)
37 bool handled_p[LAST_TS_ENUM];
38 unsigned i;
40 memset (&handled_p, 0, sizeof (handled_p));
42 /* These are the TS_* structures that are either handled or
43 explicitly ignored by the streamer routines. */
44 handled_p[TS_BASE] = true;
45 handled_p[TS_TYPED] = true;
46 handled_p[TS_COMMON] = true;
47 handled_p[TS_INT_CST] = true;
48 handled_p[TS_REAL_CST] = true;
49 handled_p[TS_FIXED_CST] = true;
50 handled_p[TS_VECTOR] = true;
51 handled_p[TS_STRING] = true;
52 handled_p[TS_COMPLEX] = true;
53 handled_p[TS_IDENTIFIER] = true;
54 handled_p[TS_DECL_MINIMAL] = true;
55 handled_p[TS_DECL_COMMON] = true;
56 handled_p[TS_DECL_WRTL] = true;
57 handled_p[TS_DECL_NON_COMMON] = true;
58 handled_p[TS_DECL_WITH_VIS] = true;
59 handled_p[TS_FIELD_DECL] = true;
60 handled_p[TS_VAR_DECL] = true;
61 handled_p[TS_PARM_DECL] = true;
62 handled_p[TS_LABEL_DECL] = true;
63 handled_p[TS_RESULT_DECL] = true;
64 handled_p[TS_CONST_DECL] = true;
65 handled_p[TS_TYPE_DECL] = true;
66 handled_p[TS_FUNCTION_DECL] = true;
67 handled_p[TS_TYPE_COMMON] = true;
68 handled_p[TS_TYPE_WITH_LANG_SPECIFIC] = true;
69 handled_p[TS_TYPE_NON_COMMON] = true;
70 handled_p[TS_LIST] = true;
71 handled_p[TS_VEC] = true;
72 handled_p[TS_EXP] = true;
73 handled_p[TS_SSA_NAME] = true;
74 handled_p[TS_BLOCK] = true;
75 handled_p[TS_BINFO] = true;
76 handled_p[TS_STATEMENT_LIST] = true;
77 handled_p[TS_CONSTRUCTOR] = true;
78 handled_p[TS_OMP_CLAUSE] = true;
79 handled_p[TS_OPTIMIZATION] = true;
80 handled_p[TS_TARGET_OPTION] = true;
81 handled_p[TS_TRANSLATION_UNIT_DECL] = true;
83 /* Anything not marked above will trigger the following assertion.
84 If this assertion triggers, it means that there is a new TS_*
85 structure that should be handled by the streamer. */
86 for (i = 0; i < LAST_TS_ENUM; i++)
87 gcc_assert (handled_p[i]);
91 /* Helper for streamer_tree_cache_insert_1. Add T to CACHE->NODES at
92 slot IX. */
94 static void
95 streamer_tree_cache_add_to_node_array (struct streamer_tree_cache_d *cache,
96 unsigned ix, tree t, hashval_t hash)
98 /* Make sure we're either replacing an old element or
99 appending consecutively. */
100 gcc_assert (ix <= cache->nodes.length ());
102 if (ix == cache->nodes.length ())
104 cache->nodes.safe_push (t);
105 if (cache->hashes.exists ())
106 cache->hashes.safe_push (hash);
108 else
110 cache->nodes[ix] = t;
111 if (cache->hashes.exists ())
112 cache->hashes[ix] = hash;
117 /* Helper for streamer_tree_cache_insert and streamer_tree_cache_insert_at.
118 CACHE, T, and IX_P are as in streamer_tree_cache_insert.
120 If INSERT_AT_NEXT_SLOT_P is true, T is inserted at the next available
121 slot in the cache. Otherwise, T is inserted at the position indicated
122 in *IX_P.
124 If T already existed in CACHE, return true. Otherwise,
125 return false. */
127 static bool
128 streamer_tree_cache_insert_1 (struct streamer_tree_cache_d *cache,
129 tree t, hashval_t hash, unsigned *ix_p,
130 bool insert_at_next_slot_p)
132 unsigned *slot;
133 unsigned ix;
134 bool existed_p;
136 gcc_assert (t);
138 slot = cache->node_map->insert (t, &existed_p);
139 if (!existed_p)
141 /* Determine the next slot to use in the cache. */
142 if (insert_at_next_slot_p)
143 ix = cache->nodes.length ();
144 else
145 ix = *ix_p;
146 *slot = ix;
148 streamer_tree_cache_add_to_node_array (cache, ix, t, hash);
150 else
152 ix = *slot;
154 if (!insert_at_next_slot_p && ix != *ix_p)
156 /* If the caller wants to insert T at a specific slot
157 location, and ENTRY->TO does not match *IX_P, add T to
158 the requested location slot. */
159 ix = *ix_p;
160 streamer_tree_cache_add_to_node_array (cache, ix, t, hash);
161 *slot = ix;
165 if (ix_p)
166 *ix_p = ix;
168 return existed_p;
172 /* Insert tree node T in CACHE. If T already existed in the cache
173 return true. Otherwise, return false.
175 If IX_P is non-null, update it with the index into the cache where
176 T has been stored. */
178 bool
179 streamer_tree_cache_insert (struct streamer_tree_cache_d *cache, tree t,
180 hashval_t hash, unsigned *ix_p)
182 return streamer_tree_cache_insert_1 (cache, t, hash, ix_p, true);
186 /* Replace the tree node with T in CACHE at slot IX. */
188 void
189 streamer_tree_cache_replace_tree (struct streamer_tree_cache_d *cache,
190 tree t, unsigned ix)
192 hashval_t hash = 0;
193 if (cache->hashes.exists ())
194 hash = streamer_tree_cache_get_hash (cache, ix);
195 if (!cache->node_map)
196 streamer_tree_cache_add_to_node_array (cache, ix, t, hash);
197 else
198 streamer_tree_cache_insert_1 (cache, t, hash, &ix, false);
202 /* Appends tree node T to CACHE, even if T already existed in it. */
204 void
205 streamer_tree_cache_append (struct streamer_tree_cache_d *cache,
206 tree t, hashval_t hash)
208 unsigned ix = cache->nodes.length ();
209 if (!cache->node_map)
210 streamer_tree_cache_add_to_node_array (cache, ix, t, hash);
211 else
212 streamer_tree_cache_insert_1 (cache, t, hash, &ix, false);
215 /* Return true if tree node T exists in CACHE, otherwise false. If IX_P is
216 not NULL, write to *IX_P the index into the cache where T is stored
217 ((unsigned)-1 if T is not found). */
219 bool
220 streamer_tree_cache_lookup (struct streamer_tree_cache_d *cache, tree t,
221 unsigned *ix_p)
223 unsigned *slot;
224 bool retval;
225 unsigned ix;
227 gcc_assert (t);
229 slot = cache->node_map->contains (t);
230 if (slot == NULL)
232 retval = false;
233 ix = -1;
235 else
237 retval = true;
238 ix = *slot;
241 if (ix_p)
242 *ix_p = ix;
244 return retval;
248 /* Record NODE in CACHE. */
250 static void
251 record_common_node (struct streamer_tree_cache_d *cache, tree node)
253 /* If we recursively end up at nodes we do not want to preload simply don't.
254 ??? We'd want to verify that this doesn't happen, or alternatively
255 do not recurse at all. */
256 if (node == char_type_node)
257 return;
259 gcc_checking_assert (node != boolean_type_node
260 && node != boolean_true_node
261 && node != boolean_false_node);
263 /* We have to make sure to fill exactly the same number of
264 elements for all frontends. That can include NULL trees.
265 As our hash table can't deal with zero entries we'll simply stream
266 a random other tree. A NULL tree never will be looked up so it
267 doesn't matter which tree we replace it with, just to be sure
268 use error_mark_node. */
269 if (!node)
270 node = error_mark_node;
272 /* ??? FIXME, devise a better hash value. But the hash needs to be equal
273 for all frontend and lto1 invocations. So just use the position
274 in the cache as hash value. */
275 streamer_tree_cache_append (cache, node, cache->nodes.length ());
277 if (POINTER_TYPE_P (node)
278 || TREE_CODE (node) == COMPLEX_TYPE
279 || TREE_CODE (node) == ARRAY_TYPE)
280 record_common_node (cache, TREE_TYPE (node));
281 else if (TREE_CODE (node) == RECORD_TYPE)
283 /* The FIELD_DECLs of structures should be shared, so that every
284 COMPONENT_REF uses the same tree node when referencing a field.
285 Pointer equality between FIELD_DECLs is used by the alias
286 machinery to compute overlapping component references (see
287 nonoverlapping_component_refs_p and
288 nonoverlapping_component_refs_of_decl_p). */
289 for (tree f = TYPE_FIELDS (node); f; f = TREE_CHAIN (f))
290 record_common_node (cache, f);
295 /* Preload common nodes into CACHE and make sure they are merged
296 properly according to the gimple type table. */
298 static void
299 preload_common_nodes (struct streamer_tree_cache_d *cache)
301 unsigned i;
303 for (i = 0; i < itk_none; i++)
304 /* Skip itk_char. char_type_node is dependent on -f[un]signed-char. */
305 if (i != itk_char)
306 record_common_node (cache, integer_types[i]);
308 for (i = 0; i < stk_type_kind_last; i++)
309 record_common_node (cache, sizetype_tab[i]);
311 for (i = 0; i < TI_MAX; i++)
312 /* Skip boolean type and constants, they are frontend dependent. */
313 if (i != TI_BOOLEAN_TYPE
314 && i != TI_BOOLEAN_FALSE
315 && i != TI_BOOLEAN_TRUE)
316 record_common_node (cache, global_trees[i]);
320 /* Create a cache of pickled nodes. */
322 struct streamer_tree_cache_d *
323 streamer_tree_cache_create (bool with_hashes, bool with_map)
325 struct streamer_tree_cache_d *cache;
327 cache = XCNEW (struct streamer_tree_cache_d);
329 if (with_map)
330 cache->node_map = new pointer_map<unsigned>;
331 cache->nodes.create (165);
332 if (with_hashes)
333 cache->hashes.create (165);
335 /* Load all the well-known tree nodes that are always created by
336 the compiler on startup. This prevents writing them out
337 unnecessarily. */
338 preload_common_nodes (cache);
340 return cache;
344 /* Delete the streamer cache C. */
346 void
347 streamer_tree_cache_delete (struct streamer_tree_cache_d *c)
349 if (c == NULL)
350 return;
352 if (c->node_map)
353 delete c->node_map;
354 c->nodes.release ();
355 c->hashes.release ();
356 free (c);