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.
1124 lines
36 KiB
C
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;
|
|
}
|