8sa1-gcc/gcc/tree-streamer-in.c
Jan Hubicka 3fb68f2e66 Optimize ODR enum streaming
it turns out that half of the global decl stream of cc1 LTO build consits
TREE_LISTS, identifiers and integer cosntats representing TYPE_VALUES of enums.
Those are streamed only to produce ODR warning and used otherwise, so this
patch moves the info to a separate section that is represented and streamed
more effectively.

This also adds place for more info that may be used for ODR diagnostics
(i.e. at the moment we do not warn when the declarations differs i.e. by the
associated member functions and their types) and the type inheritance graph
rather then poluting the global stream.

I was bit unsure what enums we want to store into the section.  All parsed
enums is probably too expensive, only those enums streamed to represent IL is
bit hard to get, so I went for those seen by free lang data.

As a plus we now get bit more precise warning because also the location of
mismatched enum CONST_DECL is streamed.

It changes:
[WPA] read 4608466 unshared trees
[WPA] read 2942094 mergeable SCCs of average size 1.365328
[WPA] 8625389 tree bodies read in total
[WPA] tree SCC table: size 524287, 247652 elements, collision ratio: 0.383702
[WPA] tree SCC max chain length 2 (size 1)
[WPA] Compared 2694442 SCCs, 228 collisions (0.000085)
[WPA] Merged 2694419 SCCs
[WPA] Merged 3731982 tree bodies
[WPA] Merged 633335 types
[WPA] 122077 types prevailed (155548 associated trees)
...
[WPA] Compression: 110593119 input bytes, 287696614 uncompressed bytes (ratio: 2.601397)
[WPA] Size of mmap'd section decls: 85628556 bytes
[WPA] Size of mmap'd section function_body: 13842928 bytes

[WPA] read 1720989 unshared trees
[WPA] read 1252217 mergeable SCCs of average size 1.858507
[WPA] 4048243 tree bodies read in total
[WPA] tree SCC table: size 524287, 226524 elements, collision ratio: 0.491759
[WPA] tree SCC max chain length 2 (size 1)
[WPA] Compared 1025693 SCCs, 196 collisions (0.000191)
[WPA] Merged 1025670 SCCs
[WPA] Merged 2063373 tree bodies
[WPA] Merged 633497 types
[WPA] 122299 types prevailed (155827 associated trees)
...
[WPA] Compression: 103428770 input bytes, 281151423 uncompressed bytes (ratio: 2.718310)
[WPA] Size of mmap'd section decls: 49390917 bytes
[WPA] Size of mmap'd section function_body: 13858258 bytes
...
[WPA] Size of mmap'd section odr_types: 29054816 bytes

So number of SCCs streamed drops to 38% and the number of unshared trees (that
are bit misnamed since it is mostly integer_cst) to 37%.

Things speeds up correspondingly, but I did not save time report from previous
build.

The enum values are still quite surprisingly large.  I may take a look into
ways getting it smaller incrementally, but it streams reasonably fast:

Time variable                                   usr           sys          wall               GGC
 phase opt and generate             :  25.20 ( 68%)  10.88 ( 72%)  36.13 ( 69%)  868060 kB ( 52%)
 phase stream in                    :   4.46 ( 12%)   0.90 (  6%)   5.38 ( 10%)  790724 kB ( 48%)
 phase stream out                   :   6.69 ( 18%)   3.32 ( 22%)  10.03 ( 19%)       8 kB (  0%)
 ipa lto gimple in                  :   0.79 (  2%)   1.86 ( 12%)   2.39 (  5%)  252612 kB ( 15%)
 ipa lto gimple out                 :   2.48 (  7%)   0.78 (  5%)   3.26 (  6%)       0 kB (  0%)
 ipa lto decl in                    :   1.71 (  5%)   0.46 (  3%)   2.34 (  4%)  417883 kB ( 25%)
 ipa lto decl out                   :   3.28 (  9%)   0.07 (  0%)   3.27 (  6%)       0 kB (  0%)
 whopr wpa I/O                      :   0.40 (  1%)   2.24 ( 15%)   2.77 (  5%)       8 kB (  0%)
 lto stream decompression           :   1.38 (  4%)   0.31 (  2%)   1.36 (  3%)       0 kB (  0%)
 ipa ODR types                      :   0.18 (  0%)   0.02 (  0%)   0.25 (  0%)       0 kB (  0%)
 ipa inlining heuristics            :  11.64 ( 31%)   1.45 ( 10%)  13.12 ( 25%)  453160 kB ( 27%)
 ipa pure const                     :   1.74 (  5%)   0.00 (  0%)   1.76 (  3%)       0 kB (  0%)
 ipa icf                            :   1.72 (  5%)   5.33 ( 35%)   7.06 ( 13%)   16593 kB (  1%)
 whopr partitioning                 :   2.22 (  6%)   0.01 (  0%)   2.23 (  4%)    5689 kB (  0%)
 TOTAL                              :  37.17         15.20         52.46        1660886 kB

LTO-bootstrapped/regtested x86_64-linux, will comit it shortly.

gcc/ChangeLog:

2020-06-03  Jan Hubicka  <hubicka@ucw.cz>

	* ipa-devirt.c: Include data-streamer.h, lto-streamer.h and
	streamer-hooks.h.
	(odr_enums): New static var.
	(struct odr_enum_val): New struct.
	(class odr_enum): New struct.
	(odr_enum_map): New hashtable.
	(odr_types_equivalent_p): Drop code testing TYPE_VALUES.
	(add_type_duplicate): Likewise.
	(free_odr_warning_data): Do not free TYPE_VALUES.
	(register_odr_enum): New function.
	(ipa_odr_summary_write): New function.
	(ipa_odr_read_section): New function.
	(ipa_odr_summary_read): New function.
	(class pass_ipa_odr): New pass.
	(make_pass_ipa_odr): New function.
	* ipa-utils.h (register_odr_enum): Declare.
	* lto-section-in.c: (lto_section_name): Add odr_types section.
	* lto-streamer.h (enum lto_section_type): Add odr_types section.
	* passes.def: Add odr_types pass.
	* lto-streamer-out.c (DFS::DFS_write_tree_body): Do not stream
	TYPE_VALUES.
	(hash_tree): Likewise.
	* tree-streamer-in.c (lto_input_ts_type_non_common_tree_pointers):
	Likewise.
	* tree-streamer-out.c (write_ts_type_non_common_tree_pointers):
	Likewise.
	* timevar.def (TV_IPA_ODR): New timervar.
	* tree-pass.h (make_pass_ipa_odr): Declare.
	* tree.c (free_lang_data_in_type): Regiser ODR types.

gcc/lto/ChangeLog:

2020-06-03  Jan Hubicka  <hubicka@ucw.cz>

	* lto-common.c (compare_tree_sccs_1): Do not compare TYPE_VALUES.

gcc/testsuite/ChangeLog:

2020-06-03  Jan Hubicka  <hubicka@ucw.cz>

	* g++.dg/lto/pr84805_0.C: Update.
2020-06-03 21:24:38 +02:00

1124 lines
36 KiB
C

/* Routines for reading trees from a file stream.
Copyright (C) 2011-2020 Free Software Foundation, Inc.
Contributed by Diego Novillo <dnovillo@google.com>
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "target.h"
#include "tree.h"
#include "gimple.h"
#include "stringpool.h"
#include "tree-streamer.h"
#include "cgraph.h"
#include "builtins.h"
#include "gomp-constants.h"
#include "stringpool.h"
#include "attribs.h"
#include "asan.h"
#include "opts.h"
/* Read a STRING_CST from the string table in DATA_IN using input
block IB. */
tree
streamer_read_string_cst (class data_in *data_in, class lto_input_block *ib)
{
unsigned int len;
const char * ptr;
ptr = streamer_read_indexed_string (data_in, ib, &len);
if (!ptr)
return NULL;
return build_string (len, ptr);
}
/* Read an IDENTIFIER from the string table in DATA_IN using input
block IB. */
static tree
input_identifier (class data_in *data_in, class lto_input_block *ib)
{
unsigned int len;
const char *ptr;
ptr = streamer_read_indexed_string (data_in, ib, &len);
if (!ptr)
return NULL;
return get_identifier_with_length (ptr, len);
}
/* Read a chain of tree nodes from input block IB. DATA_IN contains
tables and descriptors for the file being read. */
static tree
streamer_read_chain (class lto_input_block *ib, class data_in *data_in)
{
tree first, prev, curr;
/* The chain is written as NULL terminated list of trees. */
first = prev = NULL_TREE;
do
{
curr = stream_read_tree_ref (ib, data_in);
if (prev)
TREE_CHAIN (prev) = curr;
else
first = curr;
prev = curr;
}
while (curr);
return first;
}
/* Unpack all the non-pointer fields of the TS_BASE structure of
expression EXPR from bitpack BP. */
static inline void
unpack_ts_base_value_fields (struct bitpack_d *bp, tree expr)
{
/* Note that the code for EXPR has already been unpacked to create EXPR in
streamer_alloc_tree. */
if (!TYPE_P (expr))
{
TREE_SIDE_EFFECTS (expr) = (unsigned) bp_unpack_value (bp, 1);
TREE_CONSTANT (expr) = (unsigned) bp_unpack_value (bp, 1);
TREE_READONLY (expr) = (unsigned) bp_unpack_value (bp, 1);
/* TREE_PUBLIC is used on types to indicate that the type
has a TYPE_CACHED_VALUES vector. This is not streamed out,
so we skip it here. */
TREE_PUBLIC (expr) = (unsigned) bp_unpack_value (bp, 1);
}
else
bp_unpack_value (bp, 4);
TREE_ADDRESSABLE (expr) = (unsigned) bp_unpack_value (bp, 1);
TREE_THIS_VOLATILE (expr) = (unsigned) bp_unpack_value (bp, 1);
if (DECL_P (expr))
{
DECL_UNSIGNED (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_NAMELESS (expr) = (unsigned) bp_unpack_value (bp, 1);
}
else if (TYPE_P (expr))
TYPE_UNSIGNED (expr) = (unsigned) bp_unpack_value (bp, 1);
else
bp_unpack_value (bp, 1);
TREE_ASM_WRITTEN (expr) = (unsigned) bp_unpack_value (bp, 1);
if (TYPE_P (expr))
TYPE_ARTIFICIAL (expr) = (unsigned) bp_unpack_value (bp, 1);
else
TREE_NO_WARNING (expr) = (unsigned) bp_unpack_value (bp, 1);
TREE_NOTHROW (expr) = (unsigned) bp_unpack_value (bp, 1);
TREE_STATIC (expr) = (unsigned) bp_unpack_value (bp, 1);
if (TREE_CODE (expr) != TREE_BINFO)
TREE_PRIVATE (expr) = (unsigned) bp_unpack_value (bp, 1);
else
bp_unpack_value (bp, 1);
TREE_PROTECTED (expr) = (unsigned) bp_unpack_value (bp, 1);
TREE_DEPRECATED (expr) = (unsigned) bp_unpack_value (bp, 1);
if (TYPE_P (expr))
{
if (AGGREGATE_TYPE_P (expr))
TYPE_REVERSE_STORAGE_ORDER (expr) = (unsigned) bp_unpack_value (bp, 1);
else
TYPE_SATURATING (expr) = (unsigned) bp_unpack_value (bp, 1);
TYPE_ADDR_SPACE (expr) = (unsigned) bp_unpack_value (bp, 8);
}
else if (TREE_CODE (expr) == BIT_FIELD_REF || TREE_CODE (expr) == MEM_REF)
{
REF_REVERSE_STORAGE_ORDER (expr) = (unsigned) bp_unpack_value (bp, 1);
bp_unpack_value (bp, 8);
}
else if (TREE_CODE (expr) == SSA_NAME)
{
SSA_NAME_IS_DEFAULT_DEF (expr) = (unsigned) bp_unpack_value (bp, 1);
bp_unpack_value (bp, 8);
}
else if (TREE_CODE (expr) == CALL_EXPR)
{
CALL_EXPR_BY_DESCRIPTOR (expr) = (unsigned) bp_unpack_value (bp, 1);
bp_unpack_value (bp, 8);
}
else
bp_unpack_value (bp, 9);
}
/* Unpack all the non-pointer fields of the TS_INT_CST structure of
expression EXPR from bitpack BP. */
static void
unpack_ts_int_cst_value_fields (struct bitpack_d *bp, tree expr)
{
int i;
for (i = 0; i < TREE_INT_CST_EXT_NUNITS (expr); i++)
TREE_INT_CST_ELT (expr, i) = bp_unpack_var_len_int (bp);
}
/* Unpack all the non-pointer fields of the TS_REAL_CST structure of
expression EXPR from bitpack BP. */
static void
unpack_ts_real_cst_value_fields (struct bitpack_d *bp, tree expr)
{
unsigned i;
REAL_VALUE_TYPE r;
REAL_VALUE_TYPE *rp;
/* Clear all bits of the real value type so that we can later do
bitwise comparisons to see if two values are the same. */
memset (&r, 0, sizeof r);
r.cl = (unsigned) bp_unpack_value (bp, 2);
r.decimal = (unsigned) bp_unpack_value (bp, 1);
r.sign = (unsigned) bp_unpack_value (bp, 1);
r.signalling = (unsigned) bp_unpack_value (bp, 1);
r.canonical = (unsigned) bp_unpack_value (bp, 1);
r.uexp = (unsigned) bp_unpack_value (bp, EXP_BITS);
for (i = 0; i < SIGSZ; i++)
r.sig[i] = (unsigned long) bp_unpack_value (bp, HOST_BITS_PER_LONG);
rp = ggc_alloc<real_value> ();
memcpy (rp, &r, sizeof (REAL_VALUE_TYPE));
TREE_REAL_CST_PTR (expr) = rp;
}
/* Unpack all the non-pointer fields of the TS_FIXED_CST structure of
expression EXPR from bitpack BP. */
static void
unpack_ts_fixed_cst_value_fields (struct bitpack_d *bp, tree expr)
{
FIXED_VALUE_TYPE *fp = ggc_alloc<fixed_value> ();
fp->mode = as_a <scalar_mode> (bp_unpack_machine_mode (bp));
fp->data.low = bp_unpack_var_len_int (bp);
fp->data.high = bp_unpack_var_len_int (bp);
TREE_FIXED_CST_PTR (expr) = fp;
}
/* Unpack all the non-pointer fields of the TS_DECL_COMMON structure
of expression EXPR from bitpack BP. */
static void
unpack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr)
{
SET_DECL_MODE (expr, bp_unpack_machine_mode (bp));
DECL_NONLOCAL (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_VIRTUAL_P (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_IGNORED_P (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_ABSTRACT_P (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_ARTIFICIAL (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_USER_ALIGN (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_PRESERVE_P (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_EXTERNAL (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_NOT_GIMPLE_REG_P (expr) = (unsigned) bp_unpack_value (bp, 1);
SET_DECL_ALIGN (expr, (unsigned) bp_unpack_var_len_unsigned (bp));
#ifdef ACCEL_COMPILER
if (DECL_ALIGN (expr) > targetm.absolute_biggest_alignment)
SET_DECL_ALIGN (expr, targetm.absolute_biggest_alignment);
#endif
if (TREE_CODE (expr) == LABEL_DECL)
{
EH_LANDING_PAD_NR (expr) = (int) bp_unpack_var_len_unsigned (bp);
/* Always assume an initial value of -1 for LABEL_DECL_UID to
force gimple_set_bb to recreate label_to_block_map. */
LABEL_DECL_UID (expr) = -1;
}
else if (TREE_CODE (expr) == FIELD_DECL)
{
DECL_PACKED (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_NONADDRESSABLE_P (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_PADDING_P (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_FIELD_ABI_IGNORED (expr) = (unsigned) bp_unpack_value (bp, 1);
expr->decl_common.off_align = bp_unpack_value (bp, 8);
}
else if (VAR_P (expr))
{
DECL_HAS_DEBUG_EXPR_P (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_NONLOCAL_FRAME (expr) = (unsigned) bp_unpack_value (bp, 1);
}
else if (TREE_CODE (expr) == PARM_DECL)
DECL_HIDDEN_STRING_LENGTH (expr) = (unsigned) bp_unpack_value (bp, 1);
if (TREE_CODE (expr) == RESULT_DECL
|| TREE_CODE (expr) == PARM_DECL
|| VAR_P (expr))
{
DECL_BY_REFERENCE (expr) = (unsigned) bp_unpack_value (bp, 1);
if (VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
DECL_HAS_VALUE_EXPR_P (expr) = (unsigned) bp_unpack_value (bp, 1);
}
}
/* Unpack all the non-pointer fields of the TS_DECL_WRTL structure
of expression EXPR from bitpack BP. */
static void
unpack_ts_decl_wrtl_value_fields (struct bitpack_d *bp, tree expr)
{
DECL_REGISTER (expr) = (unsigned) bp_unpack_value (bp, 1);
}
/* Unpack all the non-pointer fields of the TS_DECL_WITH_VIS structure
of expression EXPR from bitpack BP. */
static void
unpack_ts_decl_with_vis_value_fields (struct bitpack_d *bp, tree expr)
{
DECL_COMMON (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_DLLIMPORT_P (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_WEAK (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_SEEN_IN_BIND_EXPR_P (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_COMDAT (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_VISIBILITY (expr) = (enum symbol_visibility) bp_unpack_value (bp, 2);
DECL_VISIBILITY_SPECIFIED (expr) = (unsigned) bp_unpack_value (bp, 1);
if (VAR_P (expr))
{
DECL_HARD_REGISTER (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_IN_CONSTANT_POOL (expr) = (unsigned) bp_unpack_value (bp, 1);
}
if (TREE_CODE (expr) == FUNCTION_DECL)
{
DECL_FINAL_P (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_CXX_CONSTRUCTOR_P (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_CXX_DESTRUCTOR_P (expr) = (unsigned) bp_unpack_value (bp, 1);
}
}
/* Unpack all the non-pointer fields of the TS_FUNCTION_DECL structure
of expression EXPR from bitpack BP. */
static void
unpack_ts_function_decl_value_fields (struct bitpack_d *bp, tree expr)
{
built_in_class cl = bp_unpack_enum (bp, built_in_class, BUILT_IN_LAST);
DECL_STATIC_CONSTRUCTOR (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_STATIC_DESTRUCTOR (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_UNINLINABLE (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_POSSIBLY_INLINED (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_IS_NOVOPS (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_IS_RETURNS_TWICE (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_IS_MALLOC (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_SET_IS_OPERATOR_NEW (expr, (unsigned) bp_unpack_value (bp, 1));
DECL_SET_IS_OPERATOR_DELETE (expr, (unsigned) bp_unpack_value (bp, 1));
DECL_DECLARED_INLINE_P (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_STATIC_CHAIN (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_NO_INLINE_WARNING_P (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (expr)
= (unsigned) bp_unpack_value (bp, 1);
DECL_NO_LIMIT_STACK (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_DISREGARD_INLINE_LIMITS (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_PURE_P (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_LOOPING_CONST_OR_PURE_P (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_IS_REPLACEABLE_OPERATOR (expr) = (unsigned) bp_unpack_value (bp, 1);
unsigned int fcode = 0;
if (cl != NOT_BUILT_IN)
{
fcode = bp_unpack_value (bp, 32);
if (cl == BUILT_IN_NORMAL && fcode >= END_BUILTINS)
fatal_error (input_location,
"machine independent builtin code out of range");
else if (cl == BUILT_IN_MD)
{
tree result = targetm.builtin_decl (fcode, true);
if (!result || result == error_mark_node)
fatal_error (input_location,
"target specific builtin not available");
}
}
set_decl_built_in_function (expr, cl, fcode);
}
/* Unpack all the non-pointer fields of the TS_TYPE_COMMON structure
of expression EXPR from bitpack BP. */
static void
unpack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr)
{
machine_mode mode;
mode = bp_unpack_machine_mode (bp);
SET_TYPE_MODE (expr, mode);
/* TYPE_NO_FORCE_BLK is private to stor-layout and need
no streaming. */
TYPE_PACKED (expr) = (unsigned) bp_unpack_value (bp, 1);
TYPE_RESTRICT (expr) = (unsigned) bp_unpack_value (bp, 1);
TYPE_USER_ALIGN (expr) = (unsigned) bp_unpack_value (bp, 1);
TYPE_READONLY (expr) = (unsigned) bp_unpack_value (bp, 1);
TYPE_LANG_FLAG_0 (expr) = (unsigned) bp_unpack_value (bp, 1);
if (RECORD_OR_UNION_TYPE_P (expr))
{
TYPE_TRANSPARENT_AGGR (expr) = (unsigned) bp_unpack_value (bp, 1);
TYPE_FINAL_P (expr) = (unsigned) bp_unpack_value (bp, 1);
TYPE_CXX_ODR_P (expr) = (unsigned) bp_unpack_value (bp, 1);
}
else if (TREE_CODE (expr) == ARRAY_TYPE)
TYPE_NONALIASED_COMPONENT (expr) = (unsigned) bp_unpack_value (bp, 1);
if (TREE_CODE (expr) == ARRAY_TYPE || TREE_CODE (expr) == INTEGER_TYPE)
TYPE_STRING_FLAG (expr) = (unsigned) bp_unpack_value (bp, 1);
if (AGGREGATE_TYPE_P (expr))
TYPE_TYPELESS_STORAGE (expr) = (unsigned) bp_unpack_value (bp, 1);
TYPE_EMPTY_P (expr) = (unsigned) bp_unpack_value (bp, 1);
TYPE_PRECISION (expr) = bp_unpack_var_len_unsigned (bp);
SET_TYPE_ALIGN (expr, bp_unpack_var_len_unsigned (bp));
#ifdef ACCEL_COMPILER
if (TYPE_ALIGN (expr) > targetm.absolute_biggest_alignment)
SET_TYPE_ALIGN (expr, targetm.absolute_biggest_alignment);
#endif
}
/* Unpack all the non-pointer fields of the TS_BLOCK structure
of expression EXPR from bitpack BP. */
static void
unpack_ts_block_value_fields (class data_in *data_in,
struct bitpack_d *bp, tree expr)
{
/* BLOCK_NUMBER is recomputed. */
stream_input_location (&BLOCK_SOURCE_LOCATION (expr), bp, data_in);
}
/* Unpack all the non-pointer fields of the TS_TRANSLATION_UNIT_DECL
structure of expression EXPR from bitpack BP. */
static void
unpack_ts_translation_unit_decl_value_fields (class data_in *data_in,
struct bitpack_d *bp, tree expr)
{
TRANSLATION_UNIT_LANGUAGE (expr) = xstrdup (bp_unpack_string (data_in, bp));
vec_safe_push (all_translation_units, expr);
}
/* Unpack all the non-pointer fields of the TS_OMP_CLAUSE
structure of expression EXPR from bitpack BP. */
static void
unpack_ts_omp_clause_value_fields (class data_in *data_in,
struct bitpack_d *bp, tree expr)
{
stream_input_location (&OMP_CLAUSE_LOCATION (expr), bp, data_in);
switch (OMP_CLAUSE_CODE (expr))
{
case OMP_CLAUSE_DEFAULT:
OMP_CLAUSE_DEFAULT_KIND (expr)
= bp_unpack_enum (bp, omp_clause_default_kind,
OMP_CLAUSE_DEFAULT_LAST);
break;
case OMP_CLAUSE_SCHEDULE:
OMP_CLAUSE_SCHEDULE_KIND (expr)
= bp_unpack_enum (bp, omp_clause_schedule_kind,
OMP_CLAUSE_SCHEDULE_LAST);
break;
case OMP_CLAUSE_DEPEND:
OMP_CLAUSE_DEPEND_KIND (expr)
= bp_unpack_enum (bp, omp_clause_depend_kind, OMP_CLAUSE_DEPEND_LAST);
break;
case OMP_CLAUSE_MAP:
OMP_CLAUSE_SET_MAP_KIND (expr, bp_unpack_enum (bp, gomp_map_kind,
GOMP_MAP_LAST));
break;
case OMP_CLAUSE_PROC_BIND:
OMP_CLAUSE_PROC_BIND_KIND (expr)
= bp_unpack_enum (bp, omp_clause_proc_bind_kind,
OMP_CLAUSE_PROC_BIND_LAST);
break;
case OMP_CLAUSE_REDUCTION:
case OMP_CLAUSE_TASK_REDUCTION:
case OMP_CLAUSE_IN_REDUCTION:
OMP_CLAUSE_REDUCTION_CODE (expr)
= bp_unpack_enum (bp, tree_code, MAX_TREE_CODES);
break;
default:
break;
}
}
/* Read all the language-independent bitfield values for EXPR from IB.
Return the partially unpacked bitpack so the caller can unpack any other
bitfield values that the writer may have written. */
void
streamer_read_tree_bitfields (class lto_input_block *ib,
class data_in *data_in, tree expr)
{
enum tree_code code;
struct bitpack_d bp;
/* Read the bitpack of non-pointer values from IB. */
bp = streamer_read_bitpack (ib);
/* The first word in BP contains the code of the tree that we
are about to read. */
if (streamer_debugging)
{
code = (enum tree_code) bp_unpack_value (&bp, 16);
lto_tag_check (lto_tree_code_to_tag (code),
lto_tree_code_to_tag (TREE_CODE (expr)));
}
code = TREE_CODE (expr);
/* Note that all these functions are highly sensitive to changes in
the types and sizes of each of the fields being packed. */
unpack_ts_base_value_fields (&bp, expr);
if (CODE_CONTAINS_STRUCT (code, TS_INT_CST))
unpack_ts_int_cst_value_fields (&bp, expr);
if (CODE_CONTAINS_STRUCT (code, TS_REAL_CST))
unpack_ts_real_cst_value_fields (&bp, expr);
if (CODE_CONTAINS_STRUCT (code, TS_FIXED_CST))
unpack_ts_fixed_cst_value_fields (&bp, expr);
if (CODE_CONTAINS_STRUCT (code, TS_DECL_MINIMAL))
stream_input_location (&DECL_SOURCE_LOCATION (expr), &bp, data_in);
if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
unpack_ts_decl_common_value_fields (&bp, expr);
if (CODE_CONTAINS_STRUCT (code, TS_DECL_WRTL))
unpack_ts_decl_wrtl_value_fields (&bp, expr);
if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
unpack_ts_decl_with_vis_value_fields (&bp, expr);
if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL))
unpack_ts_function_decl_value_fields (&bp, expr);
if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON))
unpack_ts_type_common_value_fields (&bp, expr);
if (CODE_CONTAINS_STRUCT (code, TS_EXP))
{
stream_input_location (&EXPR_CHECK (expr)->exp.locus, &bp, data_in);
if (code == MEM_REF
|| code == TARGET_MEM_REF)
{
MR_DEPENDENCE_CLIQUE (expr)
= (unsigned)bp_unpack_value (&bp, sizeof (short) * 8);
if (MR_DEPENDENCE_CLIQUE (expr) != 0)
MR_DEPENDENCE_BASE (expr)
= (unsigned)bp_unpack_value (&bp, sizeof (short) * 8);
}
else if (code == CALL_EXPR)
CALL_EXPR_IFN (expr) = bp_unpack_enum (&bp, internal_fn, IFN_LAST);
}
if (CODE_CONTAINS_STRUCT (code, TS_BLOCK))
unpack_ts_block_value_fields (data_in, &bp, expr);
if (CODE_CONTAINS_STRUCT (code, TS_TRANSLATION_UNIT_DECL))
unpack_ts_translation_unit_decl_value_fields (data_in, &bp, expr);
if (CODE_CONTAINS_STRUCT (code, TS_OPTIMIZATION))
cl_optimization_stream_in (data_in, &bp, TREE_OPTIMIZATION (expr));
if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR))
{
unsigned HOST_WIDE_INT length = bp_unpack_var_len_unsigned (&bp);
if (length > 0)
vec_safe_grow (CONSTRUCTOR_ELTS (expr), length);
}
#ifndef ACCEL_COMPILER
if (CODE_CONTAINS_STRUCT (code, TS_TARGET_OPTION))
{
cl_target_option_stream_in (data_in, &bp, TREE_TARGET_OPTION (expr));
if (targetm.target_option.post_stream_in)
targetm.target_option.post_stream_in (TREE_TARGET_OPTION (expr));
}
#endif
if (code == OMP_CLAUSE)
unpack_ts_omp_clause_value_fields (data_in, &bp, expr);
}
/* Materialize a new tree from input block IB using descriptors in
DATA_IN. The code for the new tree should match TAG. Store in
*IX_P the index into the reader cache where the new tree is stored. */
tree
streamer_alloc_tree (class lto_input_block *ib, class data_in *data_in,
enum LTO_tags tag)
{
enum tree_code code;
tree result;
result = NULL_TREE;
code = lto_tag_to_tree_code (tag);
/* We should never see an SSA_NAME tree. Only the version numbers of
SSA names are ever written out. See input_ssa_names. */
gcc_assert (code != SSA_NAME);
/* Instantiate a new tree using the header data. */
if (CODE_CONTAINS_STRUCT (code, TS_STRING))
result = streamer_read_string_cst (data_in, ib);
else if (CODE_CONTAINS_STRUCT (code, TS_IDENTIFIER))
result = input_identifier (data_in, ib);
else if (CODE_CONTAINS_STRUCT (code, TS_VEC))
{
HOST_WIDE_INT len = streamer_read_hwi (ib);
result = make_tree_vec (len);
}
else if (CODE_CONTAINS_STRUCT (code, TS_VECTOR))
{
bitpack_d bp = streamer_read_bitpack (ib);
unsigned int log2_npatterns = bp_unpack_value (&bp, 8);
unsigned int nelts_per_pattern = bp_unpack_value (&bp, 8);
result = make_vector (log2_npatterns, nelts_per_pattern);
}
else if (CODE_CONTAINS_STRUCT (code, TS_BINFO))
{
unsigned HOST_WIDE_INT len = streamer_read_uhwi (ib);
result = make_tree_binfo (len);
}
else if (CODE_CONTAINS_STRUCT (code, TS_INT_CST))
{
unsigned HOST_WIDE_INT len = streamer_read_uhwi (ib);
unsigned HOST_WIDE_INT ext_len = streamer_read_uhwi (ib);
result = make_int_cst (len, ext_len);
}
else if (code == CALL_EXPR)
{
unsigned HOST_WIDE_INT nargs = streamer_read_uhwi (ib);
return build_vl_exp (CALL_EXPR, nargs + 3);
}
else if (code == OMP_CLAUSE)
{
enum omp_clause_code subcode
= (enum omp_clause_code) streamer_read_uhwi (ib);
return build_omp_clause (UNKNOWN_LOCATION, subcode);
}
else
{
/* For all other nodes, materialize the tree with a raw
make_node call. */
result = make_node (code);
}
return result;
}
/* Read all pointer fields in the TS_COMMON structure of EXPR from input
block IB. DATA_IN contains tables and descriptors for the
file being read. */
static void
lto_input_ts_common_tree_pointers (class lto_input_block *ib,
class data_in *data_in, tree expr)
{
if (TREE_CODE (expr) != IDENTIFIER_NODE)
TREE_TYPE (expr) = stream_read_tree_ref (ib, data_in);
}
/* Read all pointer fields in the TS_VECTOR structure of EXPR from input
block IB. DATA_IN contains tables and descriptors for the
file being read. */
static void
lto_input_ts_vector_tree_pointers (class lto_input_block *ib,
class data_in *data_in, tree expr)
{
unsigned int count = vector_cst_encoded_nelts (expr);
for (unsigned int i = 0; i < count; ++i)
VECTOR_CST_ENCODED_ELT (expr, i) = stream_read_tree_ref (ib, data_in);
}
/* Read all pointer fields in the TS_POLY_INT_CST structure of EXPR from
input block IB. DATA_IN contains tables and descriptors for the
file being read. */
static void
lto_input_ts_poly_tree_pointers (class lto_input_block *ib,
class data_in *data_in, tree expr)
{
for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
POLY_INT_CST_COEFF (expr, i) = stream_read_tree_ref (ib, data_in);
}
/* Read all pointer fields in the TS_COMPLEX structure of EXPR from input
block IB. DATA_IN contains tables and descriptors for the
file being read. */
static void
lto_input_ts_complex_tree_pointers (class lto_input_block *ib,
class data_in *data_in, tree expr)
{
TREE_REALPART (expr) = stream_read_tree_ref (ib, data_in);
TREE_IMAGPART (expr) = stream_read_tree_ref (ib, data_in);
}
/* Read all pointer fields in the TS_DECL_MINIMAL structure of EXPR
from input block IB. DATA_IN contains tables and descriptors for the
file being read. */
static void
lto_input_ts_decl_minimal_tree_pointers (class lto_input_block *ib,
class data_in *data_in, tree expr)
{
DECL_NAME (expr) = stream_read_tree_ref (ib, data_in);
DECL_CONTEXT (expr) = stream_read_tree_ref (ib, data_in);
}
/* Read all pointer fields in the TS_DECL_COMMON structure of EXPR from
input block IB. DATA_IN contains tables and descriptors for the
file being read. */
static void
lto_input_ts_decl_common_tree_pointers (class lto_input_block *ib,
class data_in *data_in, tree expr)
{
DECL_SIZE (expr) = stream_read_tree_ref (ib, data_in);
DECL_SIZE_UNIT (expr) = stream_read_tree_ref (ib, data_in);
DECL_ATTRIBUTES (expr) = stream_read_tree_ref (ib, data_in);
DECL_ABSTRACT_ORIGIN (expr) = stream_read_tree_ref (ib, data_in);
if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
&& DECL_HAS_VALUE_EXPR_P (expr))
SET_DECL_VALUE_EXPR (expr, stream_read_tree_ref (ib, data_in));
if (VAR_P (expr)
&& DECL_HAS_DEBUG_EXPR_P (expr))
{
tree dexpr = stream_read_tree_ref (ib, data_in);
if (dexpr)
SET_DECL_DEBUG_EXPR (expr, dexpr);
}
}
/* Read all pointer fields in the TS_DECL_NON_COMMON structure of
EXPR from input block IB. DATA_IN contains tables and descriptors for the
file being read. */
static void
lto_input_ts_decl_non_common_tree_pointers (class lto_input_block *,
class data_in *, tree)
{
}
/* Read all pointer fields in the TS_DECL_WITH_VIS structure of EXPR
from input block IB. DATA_IN contains tables and descriptors for the
file being read. */
static void
lto_input_ts_decl_with_vis_tree_pointers (class lto_input_block *ib,
class data_in *data_in, tree expr)
{
tree id;
id = stream_read_tree_ref (ib, data_in);
if (id)
{
gcc_assert (TREE_CODE (id) == IDENTIFIER_NODE);
SET_DECL_ASSEMBLER_NAME (expr, id);
}
}
/* Read all pointer fields in the TS_FIELD_DECL structure of EXPR from
input block IB. DATA_IN contains tables and descriptors for the
file being read. */
static void
lto_input_ts_field_decl_tree_pointers (class lto_input_block *ib,
class data_in *data_in, tree expr)
{
DECL_FIELD_OFFSET (expr) = stream_read_tree_ref (ib, data_in);
DECL_BIT_FIELD_TYPE (expr) = stream_read_tree_ref (ib, data_in);
DECL_BIT_FIELD_REPRESENTATIVE (expr) = stream_read_tree_ref (ib, data_in);
DECL_FIELD_BIT_OFFSET (expr) = stream_read_tree_ref (ib, data_in);
}
/* Read all pointer fields in the TS_FUNCTION_DECL structure of EXPR
from input block IB. DATA_IN contains tables and descriptors for the
file being read. */
static void
lto_input_ts_function_decl_tree_pointers (class lto_input_block *ib,
class data_in *data_in, tree expr)
{
/* DECL_STRUCT_FUNCTION is loaded on demand by cgraph_get_body. */
DECL_FUNCTION_PERSONALITY (expr) = stream_read_tree_ref (ib, data_in);
#ifndef ACCEL_COMPILER
DECL_FUNCTION_SPECIFIC_TARGET (expr) = stream_read_tree_ref (ib, data_in);
#endif
DECL_FUNCTION_SPECIFIC_OPTIMIZATION (expr)
= stream_read_tree_ref (ib, data_in);
#ifdef ACCEL_COMPILER
{
tree opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (expr);
if (opts)
{
struct gcc_options tmp;
init_options_struct (&tmp, NULL);
cl_optimization_restore (&tmp, TREE_OPTIMIZATION (opts));
finish_options (&tmp, &global_options_set, UNKNOWN_LOCATION);
opts = build_optimization_node (&tmp);
DECL_FUNCTION_SPECIFIC_OPTIMIZATION (expr) = opts;
}
}
#endif
}
/* Read all pointer fields in the TS_TYPE_COMMON structure of EXPR from
input block IB. DATA_IN contains tables and descriptors for the file
being read. */
static void
lto_input_ts_type_common_tree_pointers (class lto_input_block *ib,
class data_in *data_in, tree expr)
{
TYPE_SIZE (expr) = stream_read_tree_ref (ib, data_in);
TYPE_SIZE_UNIT (expr) = stream_read_tree_ref (ib, data_in);
TYPE_ATTRIBUTES (expr) = stream_read_tree_ref (ib, data_in);
TYPE_NAME (expr) = stream_read_tree_ref (ib, data_in);
/* Do not stream TYPE_POINTER_TO or TYPE_REFERENCE_TO. They will be
reconstructed during fixup. */
/* Do not stream TYPE_NEXT_VARIANT, we reconstruct the variant lists
during fixup. */
TYPE_MAIN_VARIANT (expr) = stream_read_tree_ref (ib, data_in);
TYPE_CONTEXT (expr) = stream_read_tree_ref (ib, data_in);
/* TYPE_CANONICAL gets re-computed during type merging. */
TYPE_CANONICAL (expr) = NULL_TREE;
}
/* Read all pointer fields in the TS_TYPE_NON_COMMON structure of EXPR
from input block IB. DATA_IN contains tables and descriptors for the
file being read. */
static void
lto_input_ts_type_non_common_tree_pointers (class lto_input_block *ib,
class data_in *data_in,
tree expr)
{
if (TREE_CODE (expr) == ARRAY_TYPE)
TYPE_DOMAIN (expr) = stream_read_tree_ref (ib, data_in);
else if (RECORD_OR_UNION_TYPE_P (expr))
TYPE_FIELDS (expr) = streamer_read_chain (ib, data_in);
else if (TREE_CODE (expr) == FUNCTION_TYPE
|| TREE_CODE (expr) == METHOD_TYPE)
TYPE_ARG_TYPES (expr) = stream_read_tree_ref (ib, data_in);
if (!POINTER_TYPE_P (expr))
TYPE_MIN_VALUE_RAW (expr) = stream_read_tree_ref (ib, data_in);
TYPE_MAX_VALUE_RAW (expr) = stream_read_tree_ref (ib, data_in);
}
/* Read all pointer fields in the TS_LIST structure of EXPR from input
block IB. DATA_IN contains tables and descriptors for the
file being read. */
static void
lto_input_ts_list_tree_pointers (class lto_input_block *ib,
class data_in *data_in, tree expr)
{
TREE_PURPOSE (expr) = stream_read_tree_ref (ib, data_in);
TREE_VALUE (expr) = stream_read_tree_ref (ib, data_in);
TREE_CHAIN (expr) = stream_read_tree_ref (ib, data_in);
}
/* Read all pointer fields in the TS_VEC structure of EXPR from input
block IB. DATA_IN contains tables and descriptors for the
file being read. */
static void
lto_input_ts_vec_tree_pointers (class lto_input_block *ib,
class data_in *data_in, tree expr)
{
int i;
/* Note that TREE_VEC_LENGTH was read by streamer_alloc_tree to
instantiate EXPR. */
for (i = 0; i < TREE_VEC_LENGTH (expr); i++)
TREE_VEC_ELT (expr, i) = stream_read_tree_ref (ib, data_in);
}
/* Read all pointer fields in the TS_EXP structure of EXPR from input
block IB. DATA_IN contains tables and descriptors for the
file being read. */
static void
lto_input_ts_exp_tree_pointers (class lto_input_block *ib,
class data_in *data_in, tree expr)
{
int i;
tree block;
for (i = 0; i < TREE_OPERAND_LENGTH (expr); i++)
TREE_OPERAND (expr, i) = stream_read_tree_ref (ib, data_in);
block = stream_read_tree_ref (ib, data_in);
/* TODO: Block is stored in the locus information. It may make more sense to
to make it go via the location cache. */
if (block)
{
data_in->location_cache.apply_location_cache ();
TREE_SET_BLOCK (expr, block);
}
}
/* Read all pointer fields in the TS_BLOCK structure of EXPR from input
block IB. DATA_IN contains tables and descriptors for the
file being read. */
static void
lto_input_ts_block_tree_pointers (class lto_input_block *ib,
class data_in *data_in, tree expr)
{
BLOCK_VARS (expr) = streamer_read_chain (ib, data_in);
BLOCK_SUPERCONTEXT (expr) = stream_read_tree_ref (ib, data_in);
BLOCK_ABSTRACT_ORIGIN (expr) = stream_read_tree_ref (ib, data_in);
/* We may end up prevailing a decl with DECL_ORIGIN (t) != t here
which breaks the invariant that BLOCK_ABSTRACT_ORIGIN is the
ultimate origin. Fixup here.
??? This should get fixed with moving to DIE references. */
if (DECL_P (BLOCK_ORIGIN (expr)))
BLOCK_ABSTRACT_ORIGIN (expr) = DECL_ORIGIN (BLOCK_ABSTRACT_ORIGIN (expr));
/* Do not stream BLOCK_NONLOCALIZED_VARS. We cannot handle debug information
for early inlined BLOCKs so drop it on the floor instead of ICEing in
dwarf2out.c. */
/* BLOCK_FRAGMENT_ORIGIN and BLOCK_FRAGMENT_CHAIN is not live at LTO
streaming time. */
/* We re-compute BLOCK_SUBBLOCKS of our parent here instead
of streaming it. For non-BLOCK BLOCK_SUPERCONTEXTs we still
stream the child relationship explicitly. */
if (BLOCK_SUPERCONTEXT (expr)
&& TREE_CODE (BLOCK_SUPERCONTEXT (expr)) == BLOCK)
{
BLOCK_CHAIN (expr) = BLOCK_SUBBLOCKS (BLOCK_SUPERCONTEXT (expr));
BLOCK_SUBBLOCKS (BLOCK_SUPERCONTEXT (expr)) = expr;
}
/* The global block is rooted at the TU decl. Hook it here to
avoid the need to stream in this block during WPA time. */
else if (BLOCK_SUPERCONTEXT (expr)
&& TREE_CODE (BLOCK_SUPERCONTEXT (expr)) == TRANSLATION_UNIT_DECL)
DECL_INITIAL (BLOCK_SUPERCONTEXT (expr)) = expr;
/* The function-level block is connected at the time we read in
function bodies for the same reason. */
}
/* Read all pointer fields in the TS_BINFO structure of EXPR from input
block IB. DATA_IN contains tables and descriptors for the
file being read. */
static void
lto_input_ts_binfo_tree_pointers (class lto_input_block *ib,
class data_in *data_in, tree expr)
{
tree t;
/* Note that the number of slots in EXPR was read in
streamer_alloc_tree when instantiating EXPR. However, the
vector is empty so we cannot rely on vec::length to know how many
elements to read. So, this list is emitted as a 0-terminated
list on the writer side. */
do
{
t = stream_read_tree_ref (ib, data_in);
if (t)
BINFO_BASE_BINFOS (expr)->quick_push (t);
}
while (t);
BINFO_OFFSET (expr) = stream_read_tree_ref (ib, data_in);
BINFO_VTABLE (expr) = stream_read_tree_ref (ib, data_in);
/* Do not walk BINFO_INHERITANCE_CHAIN, BINFO_SUBVTT_INDEX,
BINFO_BASE_ACCESSES and BINFO_VPTR_INDEX; these are used by C++ FE
only. */
}
/* Read all pointer fields in the TS_CONSTRUCTOR structure of EXPR from
input block IB. DATA_IN contains tables and descriptors for the
file being read. */
static void
lto_input_ts_constructor_tree_pointers (class lto_input_block *ib,
class data_in *data_in, tree expr)
{
unsigned i;
for (i = 0; i < CONSTRUCTOR_NELTS (expr); i++)
{
constructor_elt e;
e.index = stream_read_tree_ref (ib, data_in);
e.value = stream_read_tree_ref (ib, data_in);
(*CONSTRUCTOR_ELTS (expr))[i] = e;
}
}
/* Read all pointer fields in the TS_OMP_CLAUSE structure of EXPR from
input block IB. DATA_IN contains tables and descriptors for the
file being read. */
static void
lto_input_ts_omp_clause_tree_pointers (class lto_input_block *ib,
class data_in *data_in, tree expr)
{
int i;
for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (expr)]; i++)
OMP_CLAUSE_OPERAND (expr, i) = stream_read_tree_ref (ib, data_in);
OMP_CLAUSE_CHAIN (expr) = stream_read_tree_ref (ib, data_in);
}
/* Read all pointer fields in EXPR from input block IB. DATA_IN
contains tables and descriptors for the file being read. */
void
streamer_read_tree_body (class lto_input_block *ib, class data_in *data_in,
tree expr)
{
enum tree_code code;
code = TREE_CODE (expr);
if (CODE_CONTAINS_STRUCT (code, TS_TYPED))
lto_input_ts_common_tree_pointers (ib, data_in, expr);
if (CODE_CONTAINS_STRUCT (code, TS_VECTOR))
lto_input_ts_vector_tree_pointers (ib, data_in, expr);
if (CODE_CONTAINS_STRUCT (code, TS_POLY_INT_CST))
lto_input_ts_poly_tree_pointers (ib, data_in, expr);
if (CODE_CONTAINS_STRUCT (code, TS_COMPLEX))
lto_input_ts_complex_tree_pointers (ib, data_in, expr);
if (CODE_CONTAINS_STRUCT (code, TS_DECL_MINIMAL))
lto_input_ts_decl_minimal_tree_pointers (ib, data_in, expr);
if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
lto_input_ts_decl_common_tree_pointers (ib, data_in, expr);
if (CODE_CONTAINS_STRUCT (code, TS_DECL_NON_COMMON))
lto_input_ts_decl_non_common_tree_pointers (ib, data_in, expr);
if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
lto_input_ts_decl_with_vis_tree_pointers (ib, data_in, expr);
if (CODE_CONTAINS_STRUCT (code, TS_FIELD_DECL))
lto_input_ts_field_decl_tree_pointers (ib, data_in, expr);
if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL))
lto_input_ts_function_decl_tree_pointers (ib, data_in, expr);
if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON))
lto_input_ts_type_common_tree_pointers (ib, data_in, expr);
if (CODE_CONTAINS_STRUCT (code, TS_TYPE_NON_COMMON))
lto_input_ts_type_non_common_tree_pointers (ib, data_in, expr);
if (CODE_CONTAINS_STRUCT (code, TS_LIST))
lto_input_ts_list_tree_pointers (ib, data_in, expr);
if (CODE_CONTAINS_STRUCT (code, TS_VEC))
lto_input_ts_vec_tree_pointers (ib, data_in, expr);
if (CODE_CONTAINS_STRUCT (code, TS_EXP))
lto_input_ts_exp_tree_pointers (ib, data_in, expr);
if (CODE_CONTAINS_STRUCT (code, TS_BLOCK))
lto_input_ts_block_tree_pointers (ib, data_in, expr);
if (CODE_CONTAINS_STRUCT (code, TS_BINFO))
lto_input_ts_binfo_tree_pointers (ib, data_in, expr);
if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR))
lto_input_ts_constructor_tree_pointers (ib, data_in, expr);
if (code == OMP_CLAUSE)
lto_input_ts_omp_clause_tree_pointers (ib, data_in, expr);
}
/* Read an index IX from input block IB and return the tree node at
DATA_IN->FILE_DATA->GLOBALS_INDEX[IX]. */
tree
streamer_get_pickled_tree (class lto_input_block *ib, class data_in *data_in)
{
unsigned HOST_WIDE_INT ix;
tree result;
enum LTO_tags expected_tag;
ix = streamer_read_uhwi (ib);
result = streamer_tree_cache_get_tree (data_in->reader_cache, ix);
if (streamer_debugging)
{
expected_tag = streamer_read_enum (ib, LTO_tags, LTO_NUM_TAGS);
gcc_assert (result
&& TREE_CODE (result) == lto_tag_to_tree_code (expected_tag));
}
return result;
}