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