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 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 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 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 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 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 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 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 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 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 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 * 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 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