]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/tree-streamer.c
2014-10-27 Andrew MacLeod <amacleod@redhat.com>
[thirdparty/gcc.git] / gcc / tree-streamer.c
CommitLineData
2541503d 1/* Miscellaneous utilities for tree streaming. Things that are used
2 in both input and output are here.
3
3aea1f79 4 Copyright (C) 2011-2014 Free Software Foundation, Inc.
2541503d 5 Contributed by Diego Novillo <dnovillo@google.com>
6
7This file is part of GCC.
8
9GCC is free software; you can redistribute it and/or modify it under
10the terms of the GNU General Public License as published by the Free
11Software Foundation; either version 3, or (at your option) any later
12version.
13
14GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15WARRANTY; without even the implied warranty of MERCHANTABILITY or
16FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17for more details.
18
19You should have received a copy of the GNU General Public License
20along with GCC; see the file COPYING3. If not see
21<http://www.gnu.org/licenses/>. */
22
23#include "config.h"
24#include "system.h"
25#include "coretypes.h"
41a8aa41 26#include "tree.h"
94ea8568 27#include "predict.h"
28#include "vec.h"
29#include "hashtab.h"
30#include "hash-set.h"
31#include "machmode.h"
32#include "tm.h"
33#include "hard-reg-set.h"
34#include "input.h"
35#include "function.h"
bc61cadb 36#include "basic-block.h"
37#include "tree-ssa-alias.h"
38#include "internal-fn.h"
39#include "gimple-expr.h"
d62dd039 40#include "hash-map.h"
bc61cadb 41#include "is-a.h"
b23fb4cb 42#include "gimple.h"
2541503d 43#include "streamer-hooks.h"
44#include "tree-streamer.h"
45
7f385784 46/* Check that all the TS_* structures handled by the streamer_write_* and
47 streamer_read_* routines are exactly ALL the structures defined in
2541503d 48 treestruct.def. */
49
50void
7f385784 51streamer_check_handled_ts_structures (void)
2541503d 52{
53 bool handled_p[LAST_TS_ENUM];
54 unsigned i;
55
56 memset (&handled_p, 0, sizeof (handled_p));
57
58 /* These are the TS_* structures that are either handled or
59 explicitly ignored by the streamer routines. */
60 handled_p[TS_BASE] = true;
61 handled_p[TS_TYPED] = true;
62 handled_p[TS_COMMON] = true;
63 handled_p[TS_INT_CST] = true;
64 handled_p[TS_REAL_CST] = true;
65 handled_p[TS_FIXED_CST] = true;
66 handled_p[TS_VECTOR] = true;
67 handled_p[TS_STRING] = true;
68 handled_p[TS_COMPLEX] = true;
69 handled_p[TS_IDENTIFIER] = true;
70 handled_p[TS_DECL_MINIMAL] = true;
71 handled_p[TS_DECL_COMMON] = true;
72 handled_p[TS_DECL_WRTL] = true;
73 handled_p[TS_DECL_NON_COMMON] = true;
74 handled_p[TS_DECL_WITH_VIS] = true;
75 handled_p[TS_FIELD_DECL] = true;
76 handled_p[TS_VAR_DECL] = true;
77 handled_p[TS_PARM_DECL] = true;
78 handled_p[TS_LABEL_DECL] = true;
79 handled_p[TS_RESULT_DECL] = true;
80 handled_p[TS_CONST_DECL] = true;
81 handled_p[TS_TYPE_DECL] = true;
82 handled_p[TS_FUNCTION_DECL] = true;
83 handled_p[TS_TYPE_COMMON] = true;
84 handled_p[TS_TYPE_WITH_LANG_SPECIFIC] = true;
85 handled_p[TS_TYPE_NON_COMMON] = true;
86 handled_p[TS_LIST] = true;
87 handled_p[TS_VEC] = true;
88 handled_p[TS_EXP] = true;
89 handled_p[TS_SSA_NAME] = true;
90 handled_p[TS_BLOCK] = true;
91 handled_p[TS_BINFO] = true;
92 handled_p[TS_STATEMENT_LIST] = true;
93 handled_p[TS_CONSTRUCTOR] = true;
94 handled_p[TS_OMP_CLAUSE] = true;
95 handled_p[TS_OPTIMIZATION] = true;
96 handled_p[TS_TARGET_OPTION] = true;
97 handled_p[TS_TRANSLATION_UNIT_DECL] = true;
98
99 /* Anything not marked above will trigger the following assertion.
100 If this assertion triggers, it means that there is a new TS_*
101 structure that should be handled by the streamer. */
102 for (i = 0; i < LAST_TS_ENUM; i++)
103 gcc_assert (handled_p[i]);
104}
105
106
7f385784 107/* Helper for streamer_tree_cache_insert_1. Add T to CACHE->NODES at
2541503d 108 slot IX. */
109
110static void
7f385784 111streamer_tree_cache_add_to_node_array (struct streamer_tree_cache_d *cache,
8ceff600 112 unsigned ix, tree t, hashval_t hash)
2541503d 113{
b1e946ea 114 /* We're either replacing an old element or appending consecutively. */
115 if (cache->nodes.exists ())
8ceff600 116 {
b1e946ea 117 if (cache->nodes.length () == ix)
118 cache->nodes.safe_push (t);
119 else
120 cache->nodes[ix] = t;
8ceff600 121 }
b1e946ea 122 if (cache->hashes.exists ())
8ceff600 123 {
b1e946ea 124 if (cache->hashes.length () == ix)
125 cache->hashes.safe_push (hash);
126 else
8ceff600 127 cache->hashes[ix] = hash;
128 }
2541503d 129}
130
131
7f385784 132/* Helper for streamer_tree_cache_insert and streamer_tree_cache_insert_at.
133 CACHE, T, and IX_P are as in streamer_tree_cache_insert.
2541503d 134
135 If INSERT_AT_NEXT_SLOT_P is true, T is inserted at the next available
136 slot in the cache. Otherwise, T is inserted at the position indicated
137 in *IX_P.
138
139 If T already existed in CACHE, return true. Otherwise,
140 return false. */
141
142static bool
7f385784 143streamer_tree_cache_insert_1 (struct streamer_tree_cache_d *cache,
8ceff600 144 tree t, hashval_t hash, unsigned *ix_p,
7f385784 145 bool insert_at_next_slot_p)
2541503d 146{
2541503d 147 bool existed_p;
148
149 gcc_assert (t);
150
d62dd039 151 unsigned int &ix = cache->node_map->get_or_insert (t, &existed_p);
ea1a929f 152 if (!existed_p)
2541503d 153 {
154 /* Determine the next slot to use in the cache. */
155 if (insert_at_next_slot_p)
b1e946ea 156 ix = cache->next_idx++;
2541503d 157 else
158 ix = *ix_p;
2541503d 159
8ceff600 160 streamer_tree_cache_add_to_node_array (cache, ix, t, hash);
2541503d 161 }
162 else
163 {
2541503d 164 if (!insert_at_next_slot_p && ix != *ix_p)
165 {
166 /* If the caller wants to insert T at a specific slot
167 location, and ENTRY->TO does not match *IX_P, add T to
168 the requested location slot. */
169 ix = *ix_p;
8ceff600 170 streamer_tree_cache_add_to_node_array (cache, ix, t, hash);
2541503d 171 }
2541503d 172 }
173
174 if (ix_p)
175 *ix_p = ix;
176
177 return existed_p;
178}
179
180
181/* Insert tree node T in CACHE. If T already existed in the cache
182 return true. Otherwise, return false.
183
184 If IX_P is non-null, update it with the index into the cache where
185 T has been stored. */
186
187bool
7f385784 188streamer_tree_cache_insert (struct streamer_tree_cache_d *cache, tree t,
8ceff600 189 hashval_t hash, unsigned *ix_p)
2541503d 190{
8ceff600 191 return streamer_tree_cache_insert_1 (cache, t, hash, ix_p, true);
2541503d 192}
193
194
8ceff600 195/* Replace the tree node with T in CACHE at slot IX. */
2541503d 196
8ceff600 197void
198streamer_tree_cache_replace_tree (struct streamer_tree_cache_d *cache,
199 tree t, unsigned ix)
2541503d 200{
8ceff600 201 hashval_t hash = 0;
202 if (cache->hashes.exists ())
203 hash = streamer_tree_cache_get_hash (cache, ix);
be1cd111 204 if (!cache->node_map)
205 streamer_tree_cache_add_to_node_array (cache, ix, t, hash);
206 else
207 streamer_tree_cache_insert_1 (cache, t, hash, &ix, false);
2541503d 208}
209
210
211/* Appends tree node T to CACHE, even if T already existed in it. */
212
213void
8ceff600 214streamer_tree_cache_append (struct streamer_tree_cache_d *cache,
215 tree t, hashval_t hash)
2541503d 216{
b1e946ea 217 unsigned ix = cache->next_idx++;
be1cd111 218 if (!cache->node_map)
219 streamer_tree_cache_add_to_node_array (cache, ix, t, hash);
220 else
221 streamer_tree_cache_insert_1 (cache, t, hash, &ix, false);
2541503d 222}
223
224/* Return true if tree node T exists in CACHE, otherwise false. If IX_P is
225 not NULL, write to *IX_P the index into the cache where T is stored
226 ((unsigned)-1 if T is not found). */
227
228bool
7f385784 229streamer_tree_cache_lookup (struct streamer_tree_cache_d *cache, tree t,
230 unsigned *ix_p)
2541503d 231{
ea1a929f 232 unsigned *slot;
2541503d 233 bool retval;
234 unsigned ix;
235
236 gcc_assert (t);
237
d62dd039 238 slot = cache->node_map->get (t);
2541503d 239 if (slot == NULL)
240 {
241 retval = false;
242 ix = -1;
243 }
244 else
245 {
246 retval = true;
ea1a929f 247 ix = *slot;
2541503d 248 }
249
250 if (ix_p)
251 *ix_p = ix;
252
253 return retval;
254}
255
256
515cf651 257/* Record NODE in CACHE. */
258
259static void
7f385784 260record_common_node (struct streamer_tree_cache_d *cache, tree node)
515cf651 261{
a61c69e6 262 /* If we recursively end up at nodes we do not want to preload simply don't.
263 ??? We'd want to verify that this doesn't happen, or alternatively
264 do not recurse at all. */
265 if (node == char_type_node)
266 return;
267
268 gcc_checking_assert (node != boolean_type_node
269 && node != boolean_true_node
0f2f1551 270 && node != boolean_false_node);
a61c69e6 271
515cf651 272 /* We have to make sure to fill exactly the same number of
273 elements for all frontends. That can include NULL trees.
274 As our hash table can't deal with zero entries we'll simply stream
275 a random other tree. A NULL tree never will be looked up so it
276 doesn't matter which tree we replace it with, just to be sure
277 use error_mark_node. */
278 if (!node)
279 node = error_mark_node;
280
8ceff600 281 /* ??? FIXME, devise a better hash value. But the hash needs to be equal
282 for all frontend and lto1 invocations. So just use the position
283 in the cache as hash value. */
284 streamer_tree_cache_append (cache, node, cache->nodes.length ());
515cf651 285
286 if (POINTER_TYPE_P (node)
287 || TREE_CODE (node) == COMPLEX_TYPE
288 || TREE_CODE (node) == ARRAY_TYPE)
7f385784 289 record_common_node (cache, TREE_TYPE (node));
515cf651 290 else if (TREE_CODE (node) == RECORD_TYPE)
291 {
292 /* The FIELD_DECLs of structures should be shared, so that every
293 COMPONENT_REF uses the same tree node when referencing a field.
294 Pointer equality between FIELD_DECLs is used by the alias
740a2cb6 295 machinery to compute overlapping component references (see
296 nonoverlapping_component_refs_p and
297 nonoverlapping_component_refs_of_decl_p). */
298 for (tree f = TYPE_FIELDS (node); f; f = TREE_CHAIN (f))
7f385784 299 record_common_node (cache, f);
515cf651 300 }
301}
302
303
304/* Preload common nodes into CACHE and make sure they are merged
305 properly according to the gimple type table. */
306
307static void
7f385784 308preload_common_nodes (struct streamer_tree_cache_d *cache)
515cf651 309{
310 unsigned i;
311
312 for (i = 0; i < itk_none; i++)
313 /* Skip itk_char. char_type_node is dependent on -f[un]signed-char. */
314 if (i != itk_char)
7f385784 315 record_common_node (cache, integer_types[i]);
515cf651 316
748e5d45 317 for (i = 0; i < stk_type_kind_last; i++)
7f385784 318 record_common_node (cache, sizetype_tab[i]);
515cf651 319
320 for (i = 0; i < TI_MAX; i++)
0f2f1551 321 /* Skip boolean type and constants, they are frontend dependent. */
515cf651 322 if (i != TI_BOOLEAN_TYPE
323 && i != TI_BOOLEAN_FALSE
0f2f1551 324 && i != TI_BOOLEAN_TRUE)
7f385784 325 record_common_node (cache, global_trees[i]);
515cf651 326}
327
328
2541503d 329/* Create a cache of pickled nodes. */
330
7f385784 331struct streamer_tree_cache_d *
b1e946ea 332streamer_tree_cache_create (bool with_hashes, bool with_map, bool with_vec)
2541503d 333{
7f385784 334 struct streamer_tree_cache_d *cache;
2541503d 335
7f385784 336 cache = XCNEW (struct streamer_tree_cache_d);
2541503d 337
be1cd111 338 if (with_map)
d62dd039 339 cache->node_map = new hash_map<tree, unsigned> (251);
b1e946ea 340 cache->next_idx = 0;
341 if (with_vec)
342 cache->nodes.create (165);
8ceff600 343 if (with_hashes)
344 cache->hashes.create (165);
2541503d 345
346 /* Load all the well-known tree nodes that are always created by
347 the compiler on startup. This prevents writing them out
348 unnecessarily. */
515cf651 349 preload_common_nodes (cache);
2541503d 350
351 return cache;
352}
353
354
355/* Delete the streamer cache C. */
356
357void
7f385784 358streamer_tree_cache_delete (struct streamer_tree_cache_d *c)
2541503d 359{
360 if (c == NULL)
361 return;
362
d62dd039 363 delete c->node_map;
364 c->node_map = NULL;
f1f41a6c 365 c->nodes.release ();
8ceff600 366 c->hashes.release ();
2541503d 367 free (c);
368}