1*38fd1498Szrj /* Miscellaneous utilities for tree streaming.  Things that are used
2*38fd1498Szrj    in both input and output are here.
3*38fd1498Szrj 
4*38fd1498Szrj    Copyright (C) 2011-2018 Free Software Foundation, Inc.
5*38fd1498Szrj    Contributed by Diego Novillo <dnovillo@google.com>
6*38fd1498Szrj 
7*38fd1498Szrj This file is part of GCC.
8*38fd1498Szrj 
9*38fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
10*38fd1498Szrj the terms of the GNU General Public License as published by the Free
11*38fd1498Szrj Software Foundation; either version 3, or (at your option) any later
12*38fd1498Szrj version.
13*38fd1498Szrj 
14*38fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15*38fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
16*38fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17*38fd1498Szrj for more details.
18*38fd1498Szrj 
19*38fd1498Szrj You should have received a copy of the GNU General Public License
20*38fd1498Szrj along with GCC; see the file COPYING3.  If not see
21*38fd1498Szrj <http://www.gnu.org/licenses/>.  */
22*38fd1498Szrj 
23*38fd1498Szrj #include "config.h"
24*38fd1498Szrj #include "system.h"
25*38fd1498Szrj #include "coretypes.h"
26*38fd1498Szrj #include "backend.h"
27*38fd1498Szrj #include "tree.h"
28*38fd1498Szrj #include "gimple.h"
29*38fd1498Szrj #include "tree-streamer.h"
30*38fd1498Szrj #include "cgraph.h"
31*38fd1498Szrj 
32*38fd1498Szrj /* Table indexed by machine_mode, used for 2 different purposes.
33*38fd1498Szrj    During streaming out we record there non-zero value for all modes
34*38fd1498Szrj    that were streamed out.
35*38fd1498Szrj    During streaming in, we translate the on the disk mode using this
36*38fd1498Szrj    table.  For normal LTO it is set to identity, for ACCEL_COMPILER
37*38fd1498Szrj    depending on the mode_table content.  */
38*38fd1498Szrj unsigned char streamer_mode_table[1 << 8];
39*38fd1498Szrj 
40*38fd1498Szrj /* Check that all the TS_* structures handled by the streamer_write_* and
41*38fd1498Szrj    streamer_read_* routines are exactly ALL the structures defined in
42*38fd1498Szrj    treestruct.def.  */
43*38fd1498Szrj 
44*38fd1498Szrj void
streamer_check_handled_ts_structures(void)45*38fd1498Szrj streamer_check_handled_ts_structures (void)
46*38fd1498Szrj {
47*38fd1498Szrj   bool handled_p[LAST_TS_ENUM];
48*38fd1498Szrj   unsigned i;
49*38fd1498Szrj 
50*38fd1498Szrj   memset (&handled_p, 0, sizeof (handled_p));
51*38fd1498Szrj 
52*38fd1498Szrj   /* These are the TS_* structures that are either handled or
53*38fd1498Szrj      explicitly ignored by the streamer routines.  */
54*38fd1498Szrj   handled_p[TS_BASE] = true;
55*38fd1498Szrj   handled_p[TS_TYPED] = true;
56*38fd1498Szrj   handled_p[TS_COMMON] = true;
57*38fd1498Szrj   handled_p[TS_INT_CST] = true;
58*38fd1498Szrj   handled_p[TS_POLY_INT_CST] = true;
59*38fd1498Szrj   handled_p[TS_REAL_CST] = true;
60*38fd1498Szrj   handled_p[TS_FIXED_CST] = true;
61*38fd1498Szrj   handled_p[TS_VECTOR] = true;
62*38fd1498Szrj   handled_p[TS_STRING] = true;
63*38fd1498Szrj   handled_p[TS_COMPLEX] = true;
64*38fd1498Szrj   handled_p[TS_IDENTIFIER] = true;
65*38fd1498Szrj   handled_p[TS_DECL_MINIMAL] = true;
66*38fd1498Szrj   handled_p[TS_DECL_COMMON] = true;
67*38fd1498Szrj   handled_p[TS_DECL_WRTL] = true;
68*38fd1498Szrj   handled_p[TS_DECL_NON_COMMON] = true;
69*38fd1498Szrj   handled_p[TS_DECL_WITH_VIS] = true;
70*38fd1498Szrj   handled_p[TS_FIELD_DECL] = true;
71*38fd1498Szrj   handled_p[TS_VAR_DECL] = true;
72*38fd1498Szrj   handled_p[TS_PARM_DECL] = true;
73*38fd1498Szrj   handled_p[TS_LABEL_DECL] = true;
74*38fd1498Szrj   handled_p[TS_RESULT_DECL] = true;
75*38fd1498Szrj   handled_p[TS_CONST_DECL] = true;
76*38fd1498Szrj   handled_p[TS_TYPE_DECL] = true;
77*38fd1498Szrj   handled_p[TS_FUNCTION_DECL] = true;
78*38fd1498Szrj   handled_p[TS_TYPE_COMMON] = true;
79*38fd1498Szrj   handled_p[TS_TYPE_WITH_LANG_SPECIFIC] = true;
80*38fd1498Szrj   handled_p[TS_TYPE_NON_COMMON] = true;
81*38fd1498Szrj   handled_p[TS_LIST] = true;
82*38fd1498Szrj   handled_p[TS_VEC] = true;
83*38fd1498Szrj   handled_p[TS_EXP] = true;
84*38fd1498Szrj   handled_p[TS_SSA_NAME] = true;
85*38fd1498Szrj   handled_p[TS_BLOCK] = true;
86*38fd1498Szrj   handled_p[TS_BINFO] = true;
87*38fd1498Szrj   handled_p[TS_STATEMENT_LIST] = true;
88*38fd1498Szrj   handled_p[TS_CONSTRUCTOR] = true;
89*38fd1498Szrj   handled_p[TS_OMP_CLAUSE] = true;
90*38fd1498Szrj   handled_p[TS_OPTIMIZATION] = true;
91*38fd1498Szrj   handled_p[TS_TARGET_OPTION] = true;
92*38fd1498Szrj   handled_p[TS_TRANSLATION_UNIT_DECL] = true;
93*38fd1498Szrj 
94*38fd1498Szrj   /* Anything not marked above will trigger the following assertion.
95*38fd1498Szrj      If this assertion triggers, it means that there is a new TS_*
96*38fd1498Szrj      structure that should be handled by the streamer.  */
97*38fd1498Szrj   for (i = 0; i < LAST_TS_ENUM; i++)
98*38fd1498Szrj     gcc_assert (handled_p[i]);
99*38fd1498Szrj }
100*38fd1498Szrj 
101*38fd1498Szrj 
102*38fd1498Szrj /* Helper for streamer_tree_cache_insert_1.  Add T to CACHE->NODES at
103*38fd1498Szrj    slot IX.  */
104*38fd1498Szrj 
105*38fd1498Szrj static void
streamer_tree_cache_add_to_node_array(struct streamer_tree_cache_d * cache,unsigned ix,tree t,hashval_t hash)106*38fd1498Szrj streamer_tree_cache_add_to_node_array (struct streamer_tree_cache_d *cache,
107*38fd1498Szrj 				       unsigned ix, tree t, hashval_t hash)
108*38fd1498Szrj {
109*38fd1498Szrj   /* We're either replacing an old element or appending consecutively.  */
110*38fd1498Szrj   if (cache->nodes.exists ())
111*38fd1498Szrj     {
112*38fd1498Szrj       if (cache->nodes.length () == ix)
113*38fd1498Szrj 	cache->nodes.safe_push (t);
114*38fd1498Szrj       else
115*38fd1498Szrj 	cache->nodes[ix] = t;
116*38fd1498Szrj     }
117*38fd1498Szrj   if (cache->hashes.exists ())
118*38fd1498Szrj     {
119*38fd1498Szrj       if (cache->hashes.length () == ix)
120*38fd1498Szrj 	cache->hashes.safe_push (hash);
121*38fd1498Szrj       else
122*38fd1498Szrj 	cache->hashes[ix] = hash;
123*38fd1498Szrj     }
124*38fd1498Szrj }
125*38fd1498Szrj 
126*38fd1498Szrj 
127*38fd1498Szrj /* Helper for streamer_tree_cache_insert and streamer_tree_cache_insert_at.
128*38fd1498Szrj    CACHE, T, and IX_P are as in streamer_tree_cache_insert.
129*38fd1498Szrj 
130*38fd1498Szrj    If INSERT_AT_NEXT_SLOT_P is true, T is inserted at the next available
131*38fd1498Szrj    slot in the cache.  Otherwise, T is inserted at the position indicated
132*38fd1498Szrj    in *IX_P.
133*38fd1498Szrj 
134*38fd1498Szrj    If T already existed in CACHE, return true.  Otherwise,
135*38fd1498Szrj    return false.  */
136*38fd1498Szrj 
137*38fd1498Szrj static bool
streamer_tree_cache_insert_1(struct streamer_tree_cache_d * cache,tree t,hashval_t hash,unsigned * ix_p,bool insert_at_next_slot_p)138*38fd1498Szrj streamer_tree_cache_insert_1 (struct streamer_tree_cache_d *cache,
139*38fd1498Szrj 			      tree t, hashval_t hash, unsigned *ix_p,
140*38fd1498Szrj 			      bool insert_at_next_slot_p)
141*38fd1498Szrj {
142*38fd1498Szrj   bool existed_p;
143*38fd1498Szrj 
144*38fd1498Szrj   gcc_assert (t);
145*38fd1498Szrj 
146*38fd1498Szrj   unsigned int &ix = cache->node_map->get_or_insert (t, &existed_p);
147*38fd1498Szrj   if (!existed_p)
148*38fd1498Szrj     {
149*38fd1498Szrj       /* Determine the next slot to use in the cache.  */
150*38fd1498Szrj       if (insert_at_next_slot_p)
151*38fd1498Szrj 	ix = cache->next_idx++;
152*38fd1498Szrj       else
153*38fd1498Szrj 	ix = *ix_p;
154*38fd1498Szrj 
155*38fd1498Szrj       streamer_tree_cache_add_to_node_array (cache, ix, t, hash);
156*38fd1498Szrj     }
157*38fd1498Szrj   else
158*38fd1498Szrj     {
159*38fd1498Szrj       if (!insert_at_next_slot_p && ix != *ix_p)
160*38fd1498Szrj 	{
161*38fd1498Szrj 	  /* If the caller wants to insert T at a specific slot
162*38fd1498Szrj 	     location, and ENTRY->TO does not match *IX_P, add T to
163*38fd1498Szrj 	     the requested location slot.  */
164*38fd1498Szrj 	  ix = *ix_p;
165*38fd1498Szrj 	  streamer_tree_cache_add_to_node_array (cache, ix, t, hash);
166*38fd1498Szrj 	}
167*38fd1498Szrj     }
168*38fd1498Szrj 
169*38fd1498Szrj   if (ix_p)
170*38fd1498Szrj     *ix_p = ix;
171*38fd1498Szrj 
172*38fd1498Szrj   return existed_p;
173*38fd1498Szrj }
174*38fd1498Szrj 
175*38fd1498Szrj 
176*38fd1498Szrj /* Insert tree node T in CACHE.  If T already existed in the cache
177*38fd1498Szrj    return true.  Otherwise, return false.
178*38fd1498Szrj 
179*38fd1498Szrj    If IX_P is non-null, update it with the index into the cache where
180*38fd1498Szrj    T has been stored.  */
181*38fd1498Szrj 
182*38fd1498Szrj bool
streamer_tree_cache_insert(struct streamer_tree_cache_d * cache,tree t,hashval_t hash,unsigned * ix_p)183*38fd1498Szrj streamer_tree_cache_insert (struct streamer_tree_cache_d *cache, tree t,
184*38fd1498Szrj 			    hashval_t hash, unsigned *ix_p)
185*38fd1498Szrj {
186*38fd1498Szrj   return streamer_tree_cache_insert_1 (cache, t, hash, ix_p, true);
187*38fd1498Szrj }
188*38fd1498Szrj 
189*38fd1498Szrj 
190*38fd1498Szrj /* Replace the tree node with T in CACHE at slot IX.  */
191*38fd1498Szrj 
192*38fd1498Szrj void
streamer_tree_cache_replace_tree(struct streamer_tree_cache_d * cache,tree t,unsigned ix)193*38fd1498Szrj streamer_tree_cache_replace_tree (struct streamer_tree_cache_d *cache,
194*38fd1498Szrj 				  tree t, unsigned ix)
195*38fd1498Szrj {
196*38fd1498Szrj   hashval_t hash = 0;
197*38fd1498Szrj   if (cache->hashes.exists ())
198*38fd1498Szrj     hash = streamer_tree_cache_get_hash (cache, ix);
199*38fd1498Szrj   if (!cache->node_map)
200*38fd1498Szrj     streamer_tree_cache_add_to_node_array (cache, ix, t, hash);
201*38fd1498Szrj   else
202*38fd1498Szrj     streamer_tree_cache_insert_1 (cache, t, hash, &ix, false);
203*38fd1498Szrj }
204*38fd1498Szrj 
205*38fd1498Szrj 
206*38fd1498Szrj /* Appends tree node T to CACHE, even if T already existed in it.  */
207*38fd1498Szrj 
208*38fd1498Szrj void
streamer_tree_cache_append(struct streamer_tree_cache_d * cache,tree t,hashval_t hash)209*38fd1498Szrj streamer_tree_cache_append (struct streamer_tree_cache_d *cache,
210*38fd1498Szrj 			    tree t, hashval_t hash)
211*38fd1498Szrj {
212*38fd1498Szrj   unsigned ix = cache->next_idx++;
213*38fd1498Szrj   if (!cache->node_map)
214*38fd1498Szrj     streamer_tree_cache_add_to_node_array (cache, ix, t, hash);
215*38fd1498Szrj   else
216*38fd1498Szrj     streamer_tree_cache_insert_1 (cache, t, hash, &ix, false);
217*38fd1498Szrj }
218*38fd1498Szrj 
219*38fd1498Szrj /* Return true if tree node T exists in CACHE, otherwise false.  If IX_P is
220*38fd1498Szrj    not NULL, write to *IX_P the index into the cache where T is stored
221*38fd1498Szrj    ((unsigned)-1 if T is not found).  */
222*38fd1498Szrj 
223*38fd1498Szrj bool
streamer_tree_cache_lookup(struct streamer_tree_cache_d * cache,tree t,unsigned * ix_p)224*38fd1498Szrj streamer_tree_cache_lookup (struct streamer_tree_cache_d *cache, tree t,
225*38fd1498Szrj 			    unsigned *ix_p)
226*38fd1498Szrj {
227*38fd1498Szrj   unsigned *slot;
228*38fd1498Szrj   bool retval;
229*38fd1498Szrj   unsigned ix;
230*38fd1498Szrj 
231*38fd1498Szrj   gcc_assert (t);
232*38fd1498Szrj 
233*38fd1498Szrj   slot = cache->node_map->get (t);
234*38fd1498Szrj   if (slot == NULL)
235*38fd1498Szrj     {
236*38fd1498Szrj       retval = false;
237*38fd1498Szrj       ix = -1;
238*38fd1498Szrj     }
239*38fd1498Szrj   else
240*38fd1498Szrj     {
241*38fd1498Szrj       retval = true;
242*38fd1498Szrj       ix = *slot;
243*38fd1498Szrj     }
244*38fd1498Szrj 
245*38fd1498Szrj   if (ix_p)
246*38fd1498Szrj     *ix_p = ix;
247*38fd1498Szrj 
248*38fd1498Szrj   return retval;
249*38fd1498Szrj }
250*38fd1498Szrj 
251*38fd1498Szrj 
252*38fd1498Szrj /* Verify that NODE is in CACHE.  */
253*38fd1498Szrj 
254*38fd1498Szrj static void
verify_common_node_recorded(struct streamer_tree_cache_d * cache,tree node)255*38fd1498Szrj verify_common_node_recorded (struct streamer_tree_cache_d *cache, tree node)
256*38fd1498Szrj {
257*38fd1498Szrj   /* Restrict this to flag_checking only because in general violating it is
258*38fd1498Szrj      harmless plus we never know what happens on all targets/frontend/flag(!)
259*38fd1498Szrj      combinations.  */
260*38fd1498Szrj   if (!flag_checking)
261*38fd1498Szrj     return;
262*38fd1498Szrj 
263*38fd1498Szrj   if (cache->node_map)
264*38fd1498Szrj     gcc_assert (streamer_tree_cache_lookup (cache, node, NULL));
265*38fd1498Szrj   else
266*38fd1498Szrj     {
267*38fd1498Szrj       bool found = false;
268*38fd1498Szrj       gcc_assert (cache->nodes.exists ());
269*38fd1498Szrj       /* Linear search...  */
270*38fd1498Szrj       for (unsigned i = 0; !found && i < cache->nodes.length (); ++i)
271*38fd1498Szrj 	if (cache->nodes[i] == node)
272*38fd1498Szrj 	  found = true;
273*38fd1498Szrj       gcc_assert (found);
274*38fd1498Szrj     }
275*38fd1498Szrj }
276*38fd1498Szrj 
277*38fd1498Szrj 
278*38fd1498Szrj /* Record NODE in CACHE.  */
279*38fd1498Szrj 
280*38fd1498Szrj static void
record_common_node(struct streamer_tree_cache_d * cache,tree node)281*38fd1498Szrj record_common_node (struct streamer_tree_cache_d *cache, tree node)
282*38fd1498Szrj {
283*38fd1498Szrj   /* If we recursively end up at nodes we do not want to preload simply don't.
284*38fd1498Szrj      ???  We'd want to verify that this doesn't happen, or alternatively
285*38fd1498Szrj      do not recurse at all.  */
286*38fd1498Szrj   if (node == char_type_node)
287*38fd1498Szrj     return;
288*38fd1498Szrj 
289*38fd1498Szrj   gcc_checking_assert (node != boolean_type_node
290*38fd1498Szrj 		       && node != boolean_true_node
291*38fd1498Szrj 		       && node != boolean_false_node);
292*38fd1498Szrj 
293*38fd1498Szrj   /* We have to make sure to fill exactly the same number of
294*38fd1498Szrj      elements for all frontends.  That can include NULL trees.
295*38fd1498Szrj      As our hash table can't deal with zero entries we'll simply stream
296*38fd1498Szrj      a random other tree.  A NULL tree never will be looked up so it
297*38fd1498Szrj      doesn't matter which tree we replace it with, just to be sure
298*38fd1498Szrj      use error_mark_node.  */
299*38fd1498Szrj   if (!node)
300*38fd1498Szrj     node = error_mark_node;
301*38fd1498Szrj 
302*38fd1498Szrj   /* ???  FIXME, devise a better hash value.  But the hash needs to be equal
303*38fd1498Szrj      for all frontend and lto1 invocations.  So just use the position
304*38fd1498Szrj      in the cache as hash value.  */
305*38fd1498Szrj   streamer_tree_cache_append (cache, node, cache->nodes.length ());
306*38fd1498Szrj 
307*38fd1498Szrj   switch (TREE_CODE (node))
308*38fd1498Szrj     {
309*38fd1498Szrj     case ERROR_MARK:
310*38fd1498Szrj     case FIELD_DECL:
311*38fd1498Szrj     case FIXED_POINT_TYPE:
312*38fd1498Szrj     case IDENTIFIER_NODE:
313*38fd1498Szrj     case INTEGER_CST:
314*38fd1498Szrj     case INTEGER_TYPE:
315*38fd1498Szrj     case POINTER_BOUNDS_TYPE:
316*38fd1498Szrj     case REAL_TYPE:
317*38fd1498Szrj     case TREE_LIST:
318*38fd1498Szrj     case VOID_CST:
319*38fd1498Szrj     case VOID_TYPE:
320*38fd1498Szrj       /* No recursive trees.  */
321*38fd1498Szrj       break;
322*38fd1498Szrj     case ARRAY_TYPE:
323*38fd1498Szrj     case POINTER_TYPE:
324*38fd1498Szrj     case REFERENCE_TYPE:
325*38fd1498Szrj       record_common_node (cache, TREE_TYPE (node));
326*38fd1498Szrj       break;
327*38fd1498Szrj     case COMPLEX_TYPE:
328*38fd1498Szrj       /* Verify that a complex type's component type (node_type) has been
329*38fd1498Szrj 	 handled already (and we thus don't need to recurse here).  */
330*38fd1498Szrj       verify_common_node_recorded (cache, TREE_TYPE (node));
331*38fd1498Szrj       break;
332*38fd1498Szrj     case RECORD_TYPE:
333*38fd1498Szrj       /* The FIELD_DECLs of structures should be shared, so that every
334*38fd1498Szrj 	 COMPONENT_REF uses the same tree node when referencing a field.
335*38fd1498Szrj 	 Pointer equality between FIELD_DECLs is used by the alias
336*38fd1498Szrj 	 machinery to compute overlapping component references (see
337*38fd1498Szrj 	 nonoverlapping_component_refs_p and
338*38fd1498Szrj 	 nonoverlapping_component_refs_of_decl_p).  */
339*38fd1498Szrj       for (tree f = TYPE_FIELDS (node); f; f = TREE_CHAIN (f))
340*38fd1498Szrj 	record_common_node (cache, f);
341*38fd1498Szrj       break;
342*38fd1498Szrj     default:
343*38fd1498Szrj       /* Unexpected tree code.  */
344*38fd1498Szrj       gcc_unreachable ();
345*38fd1498Szrj     }
346*38fd1498Szrj }
347*38fd1498Szrj 
348*38fd1498Szrj 
349*38fd1498Szrj /* Preload common nodes into CACHE and make sure they are merged
350*38fd1498Szrj    properly according to the gimple type table.  */
351*38fd1498Szrj 
352*38fd1498Szrj static void
preload_common_nodes(struct streamer_tree_cache_d * cache)353*38fd1498Szrj preload_common_nodes (struct streamer_tree_cache_d *cache)
354*38fd1498Szrj {
355*38fd1498Szrj   unsigned i;
356*38fd1498Szrj 
357*38fd1498Szrj   for (i = 0; i < itk_none; i++)
358*38fd1498Szrj     /* Skip itk_char.  char_type_node is dependent on -f[un]signed-char.  */
359*38fd1498Szrj     if (i != itk_char)
360*38fd1498Szrj       record_common_node (cache, integer_types[i]);
361*38fd1498Szrj 
362*38fd1498Szrj   for (i = 0; i < stk_type_kind_last; i++)
363*38fd1498Szrj     record_common_node (cache, sizetype_tab[i]);
364*38fd1498Szrj 
365*38fd1498Szrj   for (i = 0; i < TI_MAX; i++)
366*38fd1498Szrj     /* Skip boolean type and constants, they are frontend dependent.  */
367*38fd1498Szrj     if (i != TI_BOOLEAN_TYPE
368*38fd1498Szrj 	&& i != TI_BOOLEAN_FALSE
369*38fd1498Szrj 	&& i != TI_BOOLEAN_TRUE
370*38fd1498Szrj 	/* MAIN_IDENTIFIER is not always initialized by Fortran FE.  */
371*38fd1498Szrj 	&& i != TI_MAIN_IDENTIFIER
372*38fd1498Szrj 	/* PID_TYPE is initialized only by C family front-ends.  */
373*38fd1498Szrj 	&& i != TI_PID_TYPE
374*38fd1498Szrj 	/* Skip optimization and target option nodes; they depend on flags.  */
375*38fd1498Szrj 	&& i != TI_OPTIMIZATION_DEFAULT
376*38fd1498Szrj 	&& i != TI_OPTIMIZATION_CURRENT
377*38fd1498Szrj 	&& i != TI_TARGET_OPTION_DEFAULT
378*38fd1498Szrj 	&& i != TI_TARGET_OPTION_CURRENT
379*38fd1498Szrj 	&& i != TI_CURRENT_TARGET_PRAGMA
380*38fd1498Szrj 	&& i != TI_CURRENT_OPTIMIZE_PRAGMA
381*38fd1498Szrj 	/* Skip va_list* related nodes if offloading.  For native LTO
382*38fd1498Szrj 	   we want them to be merged for the stdarg pass, for offloading
383*38fd1498Szrj 	   they might not be identical between host and offloading target.  */
384*38fd1498Szrj 	&& (!lto_stream_offload_p
385*38fd1498Szrj 	    || (i != TI_VA_LIST_TYPE
386*38fd1498Szrj 		&& i != TI_VA_LIST_GPR_COUNTER_FIELD
387*38fd1498Szrj 		&& i != TI_VA_LIST_FPR_COUNTER_FIELD)))
388*38fd1498Szrj       record_common_node (cache, global_trees[i]);
389*38fd1498Szrj }
390*38fd1498Szrj 
391*38fd1498Szrj 
392*38fd1498Szrj /* Create a cache of pickled nodes.  */
393*38fd1498Szrj 
394*38fd1498Szrj struct streamer_tree_cache_d *
streamer_tree_cache_create(bool with_hashes,bool with_map,bool with_vec)395*38fd1498Szrj streamer_tree_cache_create (bool with_hashes, bool with_map, bool with_vec)
396*38fd1498Szrj {
397*38fd1498Szrj   struct streamer_tree_cache_d *cache;
398*38fd1498Szrj 
399*38fd1498Szrj   cache = XCNEW (struct streamer_tree_cache_d);
400*38fd1498Szrj 
401*38fd1498Szrj   if (with_map)
402*38fd1498Szrj     cache->node_map = new hash_map<tree, unsigned> (251);
403*38fd1498Szrj   cache->next_idx = 0;
404*38fd1498Szrj   if (with_vec)
405*38fd1498Szrj     cache->nodes.create (165);
406*38fd1498Szrj   if (with_hashes)
407*38fd1498Szrj     cache->hashes.create (165);
408*38fd1498Szrj 
409*38fd1498Szrj   /* Load all the well-known tree nodes that are always created by
410*38fd1498Szrj      the compiler on startup.  This prevents writing them out
411*38fd1498Szrj      unnecessarily.  */
412*38fd1498Szrj   preload_common_nodes (cache);
413*38fd1498Szrj 
414*38fd1498Szrj   return cache;
415*38fd1498Szrj }
416*38fd1498Szrj 
417*38fd1498Szrj 
418*38fd1498Szrj /* Delete the streamer cache C.  */
419*38fd1498Szrj 
420*38fd1498Szrj void
streamer_tree_cache_delete(struct streamer_tree_cache_d * c)421*38fd1498Szrj streamer_tree_cache_delete (struct streamer_tree_cache_d *c)
422*38fd1498Szrj {
423*38fd1498Szrj   if (c == NULL)
424*38fd1498Szrj     return;
425*38fd1498Szrj 
426*38fd1498Szrj   delete c->node_map;
427*38fd1498Szrj   c->node_map = NULL;
428*38fd1498Szrj   c->nodes.release ();
429*38fd1498Szrj   c->hashes.release ();
430*38fd1498Szrj   free (c);
431*38fd1498Szrj }
432