else if (TREE_CODE (t) == VAR_DECL && decl_function_context (t)
&& !TREE_STATIC (t))
return false;
+ /* Variably modified types need to be streamed alongside function
+ bodies because they can refer to local entities. Together with
+ them we have to localize their members as well.
+ ??? In theory that includes non-FIELD_DECLs as well. */
+ else if (TYPE_P (t)
+ && variably_modified_type_p (t, NULL_TREE))
+ return false;
+ else if (TREE_CODE (t) == FIELD_DECL
+ && variably_modified_type_p (DECL_CONTEXT (t), NULL_TREE))
+ return false;
else
return (TYPE_P (t) || DECL_P (t) || TREE_CODE (t) == SSA_NAME);
}
/* Emit location LOC to output block OB.
- When bitpack is handy, it is more space effecient to call
+ If the output_location streamer hook exists, call it.
+ Otherwise, when bitpack is handy, it is more space efficient to call
lto_output_location_bitpack with existing bitpack. */
void
lto_output_location (struct output_block *ob, location_t loc)
{
- struct bitpack_d bp = bitpack_create (ob->main_stream);
- lto_output_location_bitpack (&bp, ob, loc);
- streamer_write_bitpack (&bp);
+ if (streamer_hooks.output_location)
+ streamer_hooks.output_location (ob, loc);
+ else
+ {
+ struct bitpack_d bp = bitpack_create (ob->main_stream);
+ lto_output_location_bitpack (&bp, ob, loc);
+ streamer_write_bitpack (&bp);
+ }
}
&& code != WITH_CLEANUP_EXPR
&& code != STATEMENT_LIST
&& code != OMP_CLAUSE
- && code != OPTIMIZATION_NODE
&& (code == CASE_LABEL_EXPR
|| code == DECL_EXPR
|| TREE_CODE_CLASS (code) != tcc_statement);
/* Emit the physical representation of tree node EXPR to output block
- OB. If REF_P is true, the leaves of EXPR are emitted as references
- via lto_output_tree_ref. */
+ OB. If THIS_REF_P is true, the leaves of EXPR are emitted as references
+ via lto_output_tree_ref. REF_P is used for streaming siblings of EXPR. */
void
-lto_output_tree (struct output_block *ob, tree expr, bool ref_p)
+lto_output_tree (struct output_block *ob, tree expr,
+ bool ref_p, bool this_ref_p)
{
unsigned ix;
bool existed_p;
return;
}
- if (ref_p && tree_is_indexable (expr))
+ if (this_ref_p && tree_is_indexable (expr))
{
lto_output_tree_ref (ob, expr);
return;
}
-/* Output the body of function NODE->DECL. */
+/* Output the base body of struct function FN using output block OB. */
static void
-output_function (struct cgraph_node *node)
+output_struct_function_base (struct output_block *ob, struct function *fn)
{
struct bitpack_d bp;
- tree function;
- struct function *fn;
- basic_block bb;
- struct output_block *ob;
unsigned i;
tree t;
- function = node->decl;
- fn = DECL_STRUCT_FUNCTION (function);
- ob = create_output_block (LTO_section_function_body);
-
- clear_line_info (ob);
- ob->cgraph_node = node;
-
- gcc_assert (current_function_decl == NULL_TREE && cfun == NULL);
+ /* Output the static chain and non-local goto save area. */
+ stream_write_tree (ob, fn->static_chain_decl, true);
+ stream_write_tree (ob, fn->nonlocal_goto_save_area, true);
- /* Set current_function_decl and cfun. */
- current_function_decl = function;
- push_cfun (fn);
+ /* Output all the local variables in the function. */
+ streamer_write_hwi (ob, VEC_length (tree, fn->local_decls));
+ FOR_EACH_VEC_ELT (tree, fn->local_decls, i, t)
+ stream_write_tree (ob, t, true);
- /* Make string 0 be a NULL string. */
- streamer_write_char_stream (ob->string_stream, 0);
+ /* Output the function start and end loci. */
+ lto_output_location (ob, fn->function_start_locus);
+ lto_output_location (ob, fn->function_end_locus);
- streamer_write_record_start (ob, LTO_function);
+ /* Output current IL state of the function. */
+ streamer_write_uhwi (ob, fn->curr_properties);
/* Write all the attributes for FN. */
bp = bitpack_create (ob->main_stream);
bp_pack_value (&bp, fn->va_list_fpr_size, 8);
bp_pack_value (&bp, fn->va_list_gpr_size, 8);
streamer_write_bitpack (&bp);
+}
- /* Output the function start and end loci. */
- lto_output_location (ob, fn->function_start_locus);
- lto_output_location (ob, fn->function_end_locus);
- /* Output current IL state of the function. */
- streamer_write_uhwi (ob, fn->curr_properties);
+/* Output the body of function NODE->DECL. */
- /* Output the static chain and non-local goto save area. */
- stream_write_tree (ob, fn->static_chain_decl, true);
- stream_write_tree (ob, fn->nonlocal_goto_save_area, true);
+static void
+output_function (struct cgraph_node *node)
+{
+ tree function;
+ struct function *fn;
+ basic_block bb;
+ struct output_block *ob;
- /* Output all the local variables in the function. */
- streamer_write_hwi (ob, VEC_length (tree, fn->local_decls));
- FOR_EACH_VEC_ELT (tree, fn->local_decls, i, t)
- stream_write_tree (ob, t, true);
+ function = node->decl;
+ fn = DECL_STRUCT_FUNCTION (function);
+ ob = create_output_block (LTO_section_function_body);
+
+ clear_line_info (ob);
+ ob->cgraph_node = node;
+
+ gcc_assert (current_function_decl == NULL_TREE && cfun == NULL);
+
+ /* Set current_function_decl and cfun. */
+ current_function_decl = function;
+ push_cfun (fn);
+
+ /* Make string 0 be a NULL string. */
+ streamer_write_char_stream (ob->string_stream, 0);
+
+ streamer_write_record_start (ob, LTO_function);
+
+ output_struct_function_base (ob, fn);
/* Output the head of the arguments list. */
stream_write_tree (ob, DECL_ARGUMENTS (function), true);
enum gcc_plugin_symbol_kind kind;
enum gcc_plugin_symbol_visibility visibility;
unsigned slot_num;
- uint64_t size;
+ unsigned HOST_WIDEST_INT size;
const char *comdat;
unsigned char c;
when symbol has attribute (visibility("hidden")) specified.
targetm.binds_local_p check DECL_VISIBILITY_SPECIFIED and gets this
right. */
-
+
if (DECL_EXTERNAL (t)
&& !targetm.binds_local_p (t))
visibility = GCCPV_DEFAULT;
}
if (kind == GCCPK_COMMON
- && DECL_SIZE (t)
- && TREE_CODE (DECL_SIZE (t)) == INTEGER_CST)
- {
- size = (HOST_BITS_PER_WIDE_INT >= 64)
- ? (uint64_t) int_size_in_bytes (TREE_TYPE (t))
- : (((uint64_t) TREE_INT_CST_HIGH (DECL_SIZE_UNIT (t))) << 32)
- | TREE_INT_CST_LOW (DECL_SIZE_UNIT (t));
- }
+ && DECL_SIZE_UNIT (t)
+ && TREE_CODE (DECL_SIZE_UNIT (t)) == INTEGER_CST)
+ size = TREE_INT_CST_LOW (DECL_SIZE_UNIT (t));
else
size = 0;
them indirectly or via vtables. Do not output them to symbol
table: they end up being undefined and just consume space. */
if (!node->address_taken && !node->callers)
- {
- gcc_assert (node->analyzed);
- gcc_assert (DECL_DECLARED_INLINE_P (node->decl));
- continue;
- }
+ continue;
if (DECL_COMDAT (node->decl)
&& cgraph_comdat_can_be_unshared_p (node))
continue;