/* Routines for emitting trees to a file stream.
- Copyright (C) 2011-2013 Free Software Foundation, Inc.
+ Copyright (C) 2011-2018 Free Software Foundation, Inc.
Contributed by Diego Novillo <dnovillo@google.com>
This file is part of GCC.
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tm.h"
-#include "diagnostic.h"
+#include "backend.h"
+#include "target.h"
#include "tree.h"
-#include "stor-layout.h"
#include "gimple.h"
#include "tree-streamer.h"
-#include "data-streamer.h"
-#include "streamer-hooks.h"
+#include "cgraph.h"
+#include "alias.h"
+#include "stor-layout.h"
+#include "gomp-constants.h"
+
/* Output the STRING constant to the string
table in OB. Then put the index onto the INDEX_STREAM. */
/* Pack all the non-pointer fields of the TS_BASE structure of
expression EXPR into bitpack BP. */
-static void
+static inline void
pack_ts_base_value_fields (struct bitpack_d *bp, tree expr)
{
bp_pack_value (bp, TREE_CODE (expr), 16);
bp_pack_value (bp, TREE_ADDRESSABLE (expr), 1);
bp_pack_value (bp, TREE_THIS_VOLATILE (expr), 1);
if (DECL_P (expr))
- bp_pack_value (bp, DECL_UNSIGNED (expr), 1);
+ {
+ bp_pack_value (bp, DECL_UNSIGNED (expr), 1);
+ bp_pack_value (bp, DECL_NAMELESS (expr), 1);
+ }
else if (TYPE_P (expr))
bp_pack_value (bp, TYPE_UNSIGNED (expr), 1);
else
bp_pack_value (bp, TREE_STATIC (expr), 1);
if (TREE_CODE (expr) != TREE_BINFO)
bp_pack_value (bp, TREE_PRIVATE (expr), 1);
+ else
+ bp_pack_value (bp, 0, 1);
bp_pack_value (bp, TREE_PROTECTED (expr), 1);
bp_pack_value (bp, TREE_DEPRECATED (expr), 1);
if (TYPE_P (expr))
{
- bp_pack_value (bp, TYPE_SATURATING (expr), 1);
+ if (AGGREGATE_TYPE_P (expr))
+ bp_pack_value (bp, TYPE_REVERSE_STORAGE_ORDER (expr), 1);
+ else
+ bp_pack_value (bp, TYPE_SATURATING (expr), 1);
bp_pack_value (bp, TYPE_ADDR_SPACE (expr), 8);
}
+ else if (TREE_CODE (expr) == BIT_FIELD_REF || TREE_CODE (expr) == MEM_REF)
+ {
+ bp_pack_value (bp, REF_REVERSE_STORAGE_ORDER (expr), 1);
+ bp_pack_value (bp, 0, 8);
+ }
else if (TREE_CODE (expr) == SSA_NAME)
- bp_pack_value (bp, SSA_NAME_IS_DEFAULT_DEF (expr), 1);
+ {
+ bp_pack_value (bp, SSA_NAME_IS_DEFAULT_DEF (expr), 1);
+ bp_pack_value (bp, 0, 8);
+ }
+ else if (TREE_CODE (expr) == CALL_EXPR)
+ {
+ bp_pack_value (bp, CALL_EXPR_BY_DESCRIPTOR (expr), 1);
+ bp_pack_value (bp, 0, 8);
+ }
else
- bp_pack_value (bp, 0, 1);
+ bp_pack_value (bp, 0, 9);
}
static void
pack_ts_int_cst_value_fields (struct bitpack_d *bp, tree expr)
{
- bp_pack_var_len_unsigned (bp, TREE_INT_CST_LOW (expr));
- bp_pack_var_len_int (bp, TREE_INT_CST_HIGH (expr));
+ int i;
+ /* Note that the number of elements has already been written out in
+ streamer_write_tree_header. */
+ for (i = 0; i < TREE_INT_CST_EXT_NUNITS (expr); i++)
+ bp_pack_var_len_int (bp, TREE_INT_CST_ELT (expr, i));
}
pack_ts_fixed_cst_value_fields (struct bitpack_d *bp, tree expr)
{
struct fixed_value fv = TREE_FIXED_CST (expr);
- bp_pack_enum (bp, machine_mode, MAX_MACHINE_MODE, fv.mode);
+ bp_pack_machine_mode (bp, fv.mode);
bp_pack_var_len_int (bp, fv.data.low);
bp_pack_var_len_int (bp, fv.data.high);
}
static void
pack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr)
{
- bp_pack_enum (bp, machine_mode, MAX_MACHINE_MODE, DECL_MODE (expr));
+ bp_pack_machine_mode (bp, DECL_MODE (expr));
bp_pack_value (bp, DECL_NONLOCAL (expr), 1);
bp_pack_value (bp, DECL_VIRTUAL_P (expr), 1);
bp_pack_value (bp, DECL_IGNORED_P (expr), 1);
- bp_pack_value (bp, DECL_ABSTRACT (expr), 1);
+ bp_pack_value (bp, DECL_ABSTRACT_P (expr), 1);
bp_pack_value (bp, DECL_ARTIFICIAL (expr), 1);
bp_pack_value (bp, DECL_USER_ALIGN (expr), 1);
bp_pack_value (bp, DECL_PRESERVE_P (expr), 1);
bp_pack_var_len_unsigned (bp, EH_LANDING_PAD_NR (expr));
}
- if (TREE_CODE (expr) == FIELD_DECL)
+ else if (TREE_CODE (expr) == FIELD_DECL)
{
bp_pack_value (bp, DECL_PACKED (expr), 1);
bp_pack_value (bp, DECL_NONADDRESSABLE_P (expr), 1);
+ bp_pack_value (bp, DECL_PADDING_P (expr), 1);
bp_pack_value (bp, expr->decl_common.off_align, 8);
}
- if (TREE_CODE (expr) == VAR_DECL)
+ else if (VAR_P (expr))
{
bp_pack_value (bp, DECL_HAS_DEBUG_EXPR_P (expr), 1);
bp_pack_value (bp, DECL_NONLOCAL_FRAME (expr), 1);
}
+ else if (TREE_CODE (expr) == PARM_DECL)
+ bp_pack_value (bp, DECL_HIDDEN_STRING_LENGTH (expr), 1);
+
if (TREE_CODE (expr) == RESULT_DECL
|| TREE_CODE (expr) == PARM_DECL
- || TREE_CODE (expr) == VAR_DECL)
+ || VAR_P (expr))
{
bp_pack_value (bp, DECL_BY_REFERENCE (expr), 1);
- if (TREE_CODE (expr) == VAR_DECL
- || TREE_CODE (expr) == PARM_DECL)
+ if (VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
bp_pack_value (bp, DECL_HAS_VALUE_EXPR_P (expr), 1);
}
}
bp_pack_value (bp, DECL_VISIBILITY (expr), 2);
bp_pack_value (bp, DECL_VISIBILITY_SPECIFIED (expr), 1);
- if (TREE_CODE (expr) == VAR_DECL)
+ if (VAR_P (expr))
{
bp_pack_value (bp, DECL_HARD_REGISTER (expr), 1);
/* DECL_IN_TEXT_SECTION is set during final asm output only. */
bp_pack_value (bp, DECL_IN_CONSTANT_POOL (expr), 1);
- bp_pack_value (bp, DECL_TLS_MODEL (expr), 3);
}
if (TREE_CODE (expr) == FUNCTION_DECL)
bp_pack_value (bp, DECL_CXX_CONSTRUCTOR_P (expr), 1);
bp_pack_value (bp, DECL_CXX_DESTRUCTOR_P (expr), 1);
}
- if (VAR_OR_FUNCTION_DECL_P (expr))
- bp_pack_var_len_unsigned (bp, DECL_INIT_PRIORITY (expr));
}
static void
pack_ts_function_decl_value_fields (struct bitpack_d *bp, tree expr)
{
- /* For normal/md builtins we only write the class and code, so they
- should never be handled here. */
- gcc_assert (!streamer_handle_as_builtin_p (expr));
-
bp_pack_enum (bp, built_in_class, BUILT_IN_LAST,
DECL_BUILT_IN_CLASS (expr));
bp_pack_value (bp, DECL_STATIC_CONSTRUCTOR (expr), 1);
bp_pack_value (bp, DECL_PURE_P (expr), 1);
bp_pack_value (bp, DECL_LOOPING_CONST_OR_PURE_P (expr), 1);
if (DECL_BUILT_IN_CLASS (expr) != NOT_BUILT_IN)
- bp_pack_value (bp, DECL_FUNCTION_CODE (expr), 11);
- if (DECL_STATIC_DESTRUCTOR (expr))
- bp_pack_var_len_unsigned (bp, DECL_FINI_PRIORITY (expr));
+ bp_pack_value (bp, DECL_FUNCTION_CODE (expr), 12);
}
static void
pack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr)
{
- bp_pack_enum (bp, machine_mode, MAX_MACHINE_MODE, TYPE_MODE (expr));
+ /* for VECTOR_TYPE, TYPE_MODE reevaluates the mode using target_flags
+ not necessary valid in a global context.
+ Use the raw value previously set by layout_type. */
+ bp_pack_machine_mode (bp, TYPE_MODE_RAW (expr));
bp_pack_value (bp, TYPE_STRING_FLAG (expr), 1);
- bp_pack_value (bp, TYPE_NO_FORCE_BLK (expr), 1);
+ /* TYPE_NO_FORCE_BLK is private to stor-layout and need
+ no streaming. */
bp_pack_value (bp, TYPE_NEEDS_CONSTRUCTING (expr), 1);
+ bp_pack_value (bp, TYPE_PACKED (expr), 1);
+ bp_pack_value (bp, TYPE_RESTRICT (expr), 1);
+ bp_pack_value (bp, TYPE_USER_ALIGN (expr), 1);
+ bp_pack_value (bp, TYPE_READONLY (expr), 1);
+ /* We used to stream TYPE_ALIAS_SET == 0 information to let frontends mark
+ types that are opaque for TBAA. This however did not work as intended,
+ because TYPE_ALIAS_SET == 0 was regularly lost in type merging. */
if (RECORD_OR_UNION_TYPE_P (expr))
{
bp_pack_value (bp, TYPE_TRANSPARENT_AGGR (expr), 1);
}
else if (TREE_CODE (expr) == ARRAY_TYPE)
bp_pack_value (bp, TYPE_NONALIASED_COMPONENT (expr), 1);
- bp_pack_value (bp, TYPE_PACKED (expr), 1);
- bp_pack_value (bp, TYPE_RESTRICT (expr), 1);
- bp_pack_value (bp, TYPE_USER_ALIGN (expr), 1);
- bp_pack_value (bp, TYPE_READONLY (expr), 1);
+ if (AGGREGATE_TYPE_P (expr))
+ bp_pack_value (bp, TYPE_TYPELESS_STORAGE (expr), 1);
+ bp_pack_value (bp, TYPE_EMPTY_P (expr), 1);
bp_pack_var_len_unsigned (bp, TYPE_PRECISION (expr));
bp_pack_var_len_unsigned (bp, TYPE_ALIGN (expr));
- /* Make sure to preserve the fact whether the frontend would assign
- alias-set zero to this type. */
- bp_pack_var_len_int (bp, (TYPE_ALIAS_SET (expr) == 0
- || (!in_lto_p
- && get_alias_set (expr) == 0)) ? 0 : -1);
}
bp_pack_string (ob, bp, TRANSLATION_UNIT_LANGUAGE (expr), true);
}
-/* Pack a TS_TARGET_OPTION tree in EXPR to BP. */
-
-static void
-pack_ts_target_option (struct bitpack_d *bp, tree expr)
-{
- struct cl_target_option *t = TREE_TARGET_OPTION (expr);
- unsigned i, len;
-
- /* The cl_target_option is target specific and generated by the options
- awk script, so we just recreate a byte-by-byte copy here. */
-
- len = sizeof (struct cl_target_option);
- for (i = 0; i < len; i++)
- bp_pack_value (bp, ((unsigned char *)t)[i], 8);
- /* Catch struct size mismatches between reader and writer. */
- bp_pack_value (bp, 0x12345678, 32);
-}
-/* Pack a TS_OPTIMIZATION tree in EXPR to BP. */
+/* Pack all the non-pointer fields of the TS_OMP_CLAUSE structure
+ of expression EXPR into bitpack BP. */
static void
-pack_ts_optimization (struct bitpack_d *bp, tree expr)
+pack_ts_omp_clause_value_fields (struct output_block *ob,
+ struct bitpack_d *bp, tree expr)
{
- struct cl_optimization *t = TREE_OPTIMIZATION (expr);
- unsigned i, len;
-
- /* The cl_optimization is generated by the options
- awk script, so we just recreate a byte-by-byte copy here. */
-
- len = sizeof (struct cl_optimization);
- for (i = 0; i < len; i++)
- bp_pack_value (bp, ((unsigned char *)t)[i], 8);
- /* Catch struct size mismatches between reader and writer. */
- bp_pack_value (bp, 0x12345678, 32);
+ stream_output_location (ob, bp, OMP_CLAUSE_LOCATION (expr));
+ switch (OMP_CLAUSE_CODE (expr))
+ {
+ case OMP_CLAUSE_DEFAULT:
+ bp_pack_enum (bp, omp_clause_default_kind, OMP_CLAUSE_DEFAULT_LAST,
+ OMP_CLAUSE_DEFAULT_KIND (expr));
+ break;
+ case OMP_CLAUSE_SCHEDULE:
+ bp_pack_enum (bp, omp_clause_schedule_kind, OMP_CLAUSE_SCHEDULE_LAST,
+ OMP_CLAUSE_SCHEDULE_KIND (expr));
+ break;
+ case OMP_CLAUSE_DEPEND:
+ bp_pack_enum (bp, omp_clause_depend_kind, OMP_CLAUSE_DEPEND_LAST,
+ OMP_CLAUSE_DEPEND_KIND (expr));
+ break;
+ case OMP_CLAUSE_MAP:
+ bp_pack_enum (bp, gomp_map_kind, GOMP_MAP_LAST,
+ OMP_CLAUSE_MAP_KIND (expr));
+ break;
+ case OMP_CLAUSE_PROC_BIND:
+ bp_pack_enum (bp, omp_clause_proc_bind_kind, OMP_CLAUSE_PROC_BIND_LAST,
+ OMP_CLAUSE_PROC_BIND_KIND (expr));
+ break;
+ case OMP_CLAUSE_REDUCTION:
+ bp_pack_enum (bp, tree_code, MAX_TREE_CODES,
+ OMP_CLAUSE_REDUCTION_CODE (expr));
+ break;
+ default:
+ break;
+ }
}
/* Pack all the bitfields in EXPR into a bit pack. */
void
-streamer_pack_tree_bitfields (struct output_block *ob,
- struct bitpack_d *bp, tree expr)
+streamer_write_tree_bitfields (struct output_block *ob, tree expr)
{
+ bitpack_d bp = bitpack_create (ob->main_stream);
enum tree_code code;
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. */
- pack_ts_base_value_fields (bp, expr);
+ pack_ts_base_value_fields (&bp, expr);
if (CODE_CONTAINS_STRUCT (code, TS_INT_CST))
- pack_ts_int_cst_value_fields (bp, expr);
+ pack_ts_int_cst_value_fields (&bp, expr);
if (CODE_CONTAINS_STRUCT (code, TS_REAL_CST))
- pack_ts_real_cst_value_fields (bp, expr);
+ pack_ts_real_cst_value_fields (&bp, expr);
if (CODE_CONTAINS_STRUCT (code, TS_FIXED_CST))
- pack_ts_fixed_cst_value_fields (bp, expr);
+ pack_ts_fixed_cst_value_fields (&bp, expr);
if (CODE_CONTAINS_STRUCT (code, TS_DECL_MINIMAL))
- stream_output_location (ob, bp, DECL_SOURCE_LOCATION (expr));
+ stream_output_location (ob, &bp, DECL_SOURCE_LOCATION (expr));
if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
- pack_ts_decl_common_value_fields (bp, expr);
+ pack_ts_decl_common_value_fields (&bp, expr);
if (CODE_CONTAINS_STRUCT (code, TS_DECL_WRTL))
- pack_ts_decl_wrtl_value_fields (bp, expr);
+ pack_ts_decl_wrtl_value_fields (&bp, expr);
if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
- pack_ts_decl_with_vis_value_fields (bp, expr);
+ pack_ts_decl_with_vis_value_fields (&bp, expr);
if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL))
- pack_ts_function_decl_value_fields (bp, expr);
+ pack_ts_function_decl_value_fields (&bp, expr);
if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON))
- pack_ts_type_common_value_fields (bp, expr);
+ pack_ts_type_common_value_fields (&bp, expr);
if (CODE_CONTAINS_STRUCT (code, TS_EXP))
- stream_output_location (ob, bp, EXPR_LOCATION (expr));
+ {
+ stream_output_location (ob, &bp, EXPR_LOCATION (expr));
+ if (code == MEM_REF
+ || code == TARGET_MEM_REF)
+ {
+ bp_pack_value (&bp, MR_DEPENDENCE_CLIQUE (expr), sizeof (short) * 8);
+ if (MR_DEPENDENCE_CLIQUE (expr) != 0)
+ bp_pack_value (&bp, MR_DEPENDENCE_BASE (expr), sizeof (short) * 8);
+ }
+ else if (code == CALL_EXPR)
+ bp_pack_enum (&bp, internal_fn, IFN_LAST, CALL_EXPR_IFN (expr));
+ }
if (CODE_CONTAINS_STRUCT (code, TS_BLOCK))
- pack_ts_block_value_fields (ob, bp, expr);
+ pack_ts_block_value_fields (ob, &bp, expr);
if (CODE_CONTAINS_STRUCT (code, TS_TRANSLATION_UNIT_DECL))
- pack_ts_translation_unit_decl_value_fields (ob, bp, expr);
-
- if (CODE_CONTAINS_STRUCT (code, TS_TARGET_OPTION))
- pack_ts_target_option (bp, expr);
+ pack_ts_translation_unit_decl_value_fields (ob, &bp, expr);
if (CODE_CONTAINS_STRUCT (code, TS_OPTIMIZATION))
- pack_ts_optimization (bp, expr);
+ cl_optimization_stream_out (&bp, TREE_OPTIMIZATION (expr));
if (CODE_CONTAINS_STRUCT (code, TS_BINFO))
- bp_pack_var_len_unsigned (bp, vec_safe_length (BINFO_BASE_ACCESSES (expr)));
+ bp_pack_var_len_unsigned (&bp, vec_safe_length (BINFO_BASE_ACCESSES (expr)));
if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR))
- bp_pack_var_len_unsigned (bp, CONSTRUCTOR_NELTS (expr));
-}
-
-
-/* Write the code and class of builtin EXPR to output block OB. IX is
- the index into the streamer cache where EXPR is stored.*/
-
-void
-streamer_write_builtin (struct output_block *ob, tree expr)
-{
- gcc_assert (streamer_handle_as_builtin_p (expr));
+ bp_pack_var_len_unsigned (&bp, CONSTRUCTOR_NELTS (expr));
- if (DECL_BUILT_IN_CLASS (expr) == BUILT_IN_MD
- && !targetm.builtin_decl)
- sorry ("tree bytecode streams do not support machine specific builtin "
- "functions on this target");
+ if (CODE_CONTAINS_STRUCT (code, TS_TARGET_OPTION)
+ /* Don't stream these when passing things to a different target. */
+ && !lto_stream_offload_p)
+ cl_target_option_stream_out (ob, &bp, TREE_TARGET_OPTION (expr));
- streamer_write_record_start (ob, LTO_builtin_decl);
- streamer_write_enum (ob->main_stream, built_in_class, BUILT_IN_LAST,
- DECL_BUILT_IN_CLASS (expr));
- streamer_write_uhwi (ob, DECL_FUNCTION_CODE (expr));
+ if (code == OMP_CLAUSE)
+ pack_ts_omp_clause_value_fields (ob, &bp, expr);
- if (DECL_ASSEMBLER_NAME_SET_P (expr))
- {
- /* When the assembler name of a builtin gets a user name,
- the new name is always prefixed with '*' by
- set_builtin_user_assembler_name. So, to prevent the
- reader side from adding a second '*', we omit it here. */
- const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (expr));
- if (strlen (str) > 1 && str[0] == '*')
- streamer_write_string (ob, ob->main_stream, &str[1], true);
- else
- streamer_write_string (ob, ob->main_stream, NULL, true);
- }
- else
- streamer_write_string (ob, ob->main_stream, NULL, true);
+ streamer_write_bitpack (&bp);
}
{
while (t)
{
- tree saved_chain;
-
- /* Clear TREE_CHAIN to avoid blindly recursing into the rest
- of the list. */
- saved_chain = TREE_CHAIN (t);
- TREE_CHAIN (t) = NULL_TREE;
-
/* We avoid outputting external vars or functions by reference
to the global decls section as we do not want to have them
enter decl merging. This is, of course, only for the call
- for streaming BLOCK_VARS, but other callers are safe. */
- /* ??? FIXME wrt SCC streaming. Drop these for now. */
+ for streaming BLOCK_VARS, but other callers are safe.
+ See also lto-streamer-out.c:DFS_write_tree_body. */
if (VAR_OR_FUNCTION_DECL_P (t)
&& DECL_EXTERNAL (t))
- ; /* stream_write_tree_shallow_non_ref (ob, t, ref_p); */
+ stream_write_tree_shallow_non_ref (ob, t, ref_p);
else
stream_write_tree (ob, t, ref_p);
- TREE_CHAIN (t) = saved_chain;
t = TREE_CHAIN (t);
}
static void
write_ts_vector_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
{
- unsigned i;
/* Note that the number of elements for EXPR has already been emitted
in EXPR's header (see streamer_write_tree_header). */
- for (i = 0; i < VECTOR_CST_NELTS (expr); ++i)
- stream_write_tree (ob, VECTOR_CST_ELT (expr, i), ref_p);
+ unsigned int count = vector_cst_encoded_nelts (expr);
+ for (unsigned int i = 0; i < count; ++i)
+ stream_write_tree (ob, VECTOR_CST_ENCODED_ELT (expr, i), ref_p);
+}
+
+
+/* Write all pointer fields in the TS_POLY_INT_CST structure of EXPR to
+ output block OB. If REF_P is true, write a reference to EXPR's pointer
+ fields. */
+
+static void
+write_ts_poly_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
+{
+ for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
+ stream_write_tree (ob, POLY_INT_CST_COEFF (expr, i), ref_p);
}
/* Drop names that were created for anonymous entities. */
if (DECL_NAME (expr)
&& TREE_CODE (DECL_NAME (expr)) == IDENTIFIER_NODE
- && ANON_AGGRNAME_P (DECL_NAME (expr)))
+ && anon_aggrname_p (DECL_NAME (expr)))
stream_write_tree (ob, NULL_TREE, ref_p);
else
stream_write_tree (ob, DECL_NAME (expr), ref_p);
- stream_write_tree (ob, DECL_CONTEXT (expr), ref_p);
+ if (TREE_CODE (expr) != TRANSLATION_UNIT_DECL
+ && ! DECL_CONTEXT (expr))
+ stream_write_tree (ob, (*all_translation_units)[0], ref_p);
+ else
+ stream_write_tree (ob, DECL_CONTEXT (expr), ref_p);
}
stream_write_tree (ob, DECL_ATTRIBUTES (expr), ref_p);
- /* Do not stream DECL_ABSTRACT_ORIGIN. We cannot handle debug information
- for early inlining so drop it on the floor instead of ICEing in
- dwarf2out.c. */
-
- if ((TREE_CODE (expr) == VAR_DECL
- || TREE_CODE (expr) == PARM_DECL)
+ /* On non-early-LTO enabled targets we claim we compiled with -g0
+ but dwarf2out still did its set_decl_origin_self game fooling
+ itself late. Und that here since we won't have access to the
+ early generated abstract DIEs. */
+ tree ao = DECL_ABSTRACT_ORIGIN (expr);
+ if (debug_info_level == DINFO_LEVEL_NONE
+ && ao == expr)
+ ao = NULL_TREE;
+ stream_write_tree (ob, ao, ref_p);
+
+ if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
&& DECL_HAS_VALUE_EXPR_P (expr))
stream_write_tree (ob, DECL_VALUE_EXPR (expr), ref_p);
- if (TREE_CODE (expr) == VAR_DECL)
+ if (VAR_P (expr)
+ && DECL_HAS_DEBUG_EXPR_P (expr))
stream_write_tree (ob, DECL_DEBUG_EXPR (expr), ref_p);
}
{
if (TREE_CODE (expr) == TYPE_DECL)
stream_write_tree (ob, DECL_ORIGINAL_TYPE (expr), ref_p);
- stream_write_tree (ob, DECL_VINDEX (expr), ref_p);
}
stream_write_tree (ob, DECL_ASSEMBLER_NAME (expr), ref_p);
else
stream_write_tree (ob, NULL_TREE, false);
-
- stream_write_tree (ob, DECL_SECTION_NAME (expr), ref_p);
- stream_write_tree (ob, DECL_COMDAT_GROUP (expr), ref_p);
}
write_ts_function_decl_tree_pointers (struct output_block *ob, tree expr,
bool ref_p)
{
- /* DECL_STRUCT_FUNCTION is handled by lto_output_function. FIXME lto,
- maybe it should be handled here? */
+ stream_write_tree (ob, DECL_VINDEX (expr), ref_p);
+ /* DECL_STRUCT_FUNCTION is handled by lto_output_function. */
stream_write_tree (ob, DECL_FUNCTION_PERSONALITY (expr), ref_p);
- stream_write_tree (ob, DECL_FUNCTION_SPECIFIC_TARGET (expr), ref_p);
+ /* Don't stream these when passing things to a different target. */
+ if (!lto_stream_offload_p)
+ stream_write_tree (ob, DECL_FUNCTION_SPECIFIC_TARGET (expr), ref_p);
stream_write_tree (ob, DECL_FUNCTION_SPECIFIC_OPTIMIZATION (expr), ref_p);
}
stream_write_tree (ob, TYPE_ARG_TYPES (expr), ref_p);
if (!POINTER_TYPE_P (expr))
- stream_write_tree (ob, TYPE_MINVAL (expr), ref_p);
- stream_write_tree (ob, TYPE_MAXVAL (expr), ref_p);
- if (RECORD_OR_UNION_TYPE_P (expr))
- stream_write_tree (ob, TYPE_BINFO (expr), ref_p);
+ stream_write_tree (ob, TYPE_MIN_VALUE_RAW (expr), ref_p);
+ stream_write_tree (ob, TYPE_MAX_VALUE_RAW (expr), ref_p);
}
/* Stream BLOCK_ABSTRACT_ORIGIN for the limited cases we can handle - those
that represent inlined function scopes.
- For the rest them on the floor instead of ICEing in dwarf2out.c. */
+ For the rest them on the floor instead of ICEing in dwarf2out.c, but
+ keep the notion of whether the block is an inlined block by refering
+ to itself for the sake of tree_nonartificial_location. */
if (inlined_function_outer_scope_p (expr))
{
tree ultimate_origin = block_ultimate_origin (expr);
stream_write_tree (ob, ultimate_origin, ref_p);
}
else
- stream_write_tree (ob, NULL_TREE, ref_p);
+ stream_write_tree (ob, (BLOCK_ABSTRACT_ORIGIN (expr)
+ ? expr : NULL_TREE), ref_p);
/* 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. */
}
}
+
+/* Write all pointer fields in the TS_OMP_CLAUSE structure of EXPR
+ to output block OB. If REF_P is true, write a reference to EXPR's
+ pointer fields. */
+
+static void
+write_ts_omp_clause_tree_pointers (struct output_block *ob, tree expr,
+ bool ref_p)
+{
+ int i;
+ for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (expr)]; i++)
+ stream_write_tree (ob, OMP_CLAUSE_OPERAND (expr, i), ref_p);
+ if (OMP_CLAUSE_CODE (expr) == OMP_CLAUSE_REDUCTION)
+ {
+ /* We don't stream these right now, handle it if streaming
+ of them is needed. */
+ gcc_assert (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (expr) == NULL);
+ gcc_assert (OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (expr) == NULL);
+ }
+ stream_write_tree (ob, OMP_CLAUSE_CHAIN (expr), ref_p);
+}
+
+
/* Write all pointer fields in EXPR to output block OB. If REF_P is true,
the leaves of EXPR are emitted as references. */
if (CODE_CONTAINS_STRUCT (code, TS_VECTOR))
write_ts_vector_tree_pointers (ob, expr, ref_p);
+ if (CODE_CONTAINS_STRUCT (code, TS_POLY_INT_CST))
+ write_ts_poly_tree_pointers (ob, expr, ref_p);
+
if (CODE_CONTAINS_STRUCT (code, TS_COMPLEX))
write_ts_complex_tree_pointers (ob, expr, ref_p);
if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR))
write_ts_constructor_tree_pointers (ob, expr, ref_p);
+
+ if (code == OMP_CLAUSE)
+ write_ts_omp_clause_tree_pointers (ob, expr, ref_p);
}
tag = lto_tree_code_to_tag (code);
streamer_write_record_start (ob, tag);
- /* The following will cause bootstrap miscomparisons. Enable with care. */
-#ifdef LTO_STREAMER_DEBUG
- /* This is used mainly for debugging purposes. When the reader
- and the writer do not agree on a streamed node, the pointer
- value for EXPR can be used to track down the differences in
- the debugger. */
- gcc_assert ((HOST_WIDEST_INT) (intptr_t) expr == (intptr_t) expr);
- streamer_write_hwi (ob, (HOST_WIDEST_INT) (intptr_t) expr);
-#endif
-
/* The text in strings and identifiers are completely emitted in
the header. */
if (CODE_CONTAINS_STRUCT (code, TS_STRING))
else if (CODE_CONTAINS_STRUCT (code, TS_IDENTIFIER))
write_identifier (ob, ob->main_stream, expr);
else if (CODE_CONTAINS_STRUCT (code, TS_VECTOR))
- streamer_write_hwi (ob, VECTOR_CST_NELTS (expr));
+ {
+ bitpack_d bp = bitpack_create (ob->main_stream);
+ bp_pack_value (&bp, VECTOR_CST_LOG2_NPATTERNS (expr), 8);
+ bp_pack_value (&bp, VECTOR_CST_NELTS_PER_PATTERN (expr), 8);
+ streamer_write_bitpack (&bp);
+ }
else if (CODE_CONTAINS_STRUCT (code, TS_VEC))
streamer_write_hwi (ob, TREE_VEC_LENGTH (expr));
else if (CODE_CONTAINS_STRUCT (code, TS_BINFO))
streamer_write_uhwi (ob, BINFO_N_BASE_BINFOS (expr));
else if (TREE_CODE (expr) == CALL_EXPR)
streamer_write_uhwi (ob, call_expr_nargs (expr));
+ else if (TREE_CODE (expr) == OMP_CLAUSE)
+ streamer_write_uhwi (ob, OMP_CLAUSE_CODE (expr));
+ else if (CODE_CONTAINS_STRUCT (code, TS_INT_CST))
+ {
+ gcc_checking_assert (TREE_INT_CST_NUNITS (expr));
+ streamer_write_uhwi (ob, TREE_INT_CST_NUNITS (expr));
+ streamer_write_uhwi (ob, TREE_INT_CST_EXT_NUNITS (expr));
+ }
}
void
streamer_write_integer_cst (struct output_block *ob, tree cst, bool ref_p)
{
+ int i;
+ int len = TREE_INT_CST_NUNITS (cst);
gcc_assert (!TREE_OVERFLOW (cst));
streamer_write_record_start (ob, LTO_integer_cst);
stream_write_tree (ob, TREE_TYPE (cst), ref_p);
- streamer_write_uhwi (ob, TREE_INT_CST_LOW (cst));
- streamer_write_hwi (ob, TREE_INT_CST_HIGH (cst));
+ /* We're effectively streaming a non-sign-extended wide_int here,
+ so there's no need to stream TREE_INT_CST_EXT_NUNITS or any
+ array members beyond LEN. We'll recreate the tree from the
+ wide_int and the type. */
+ streamer_write_uhwi (ob, len);
+ for (i = 0; i < len; i++)
+ streamer_write_hwi (ob, TREE_INT_CST_ELT (cst, i));
}