#include "flags.h"
#include "params.h"
#include "input.h"
-#include "varray.h"
#include "hashtab.h"
#include "basic-block.h"
#include "tree-flow.h"
#include "cgraph.h"
#include "function.h"
#include "ggc.h"
-#include "diagnostic.h"
+#include "diagnostic-core.h"
#include "except.h"
#include "vec.h"
#include "lto-symtab.h"
}
-/* Output bitpack BP to output stream S. */
-
-void
-lto_output_bitpack (struct lto_output_stream *s, struct bitpack_d *bp)
-{
- unsigned i;
- bitpack_word_t v;
-
- lto_output_uleb128_stream (s, VEC_length (bitpack_word_t, bp->values));
- for (i = 0; VEC_iterate (bitpack_word_t, bp->values, i, v); i++)
- lto_output_uleb128_stream (s, v);
-}
-
-
/* Output STRING of LEN characters to the string
table in OB. The string might or might not include a trailing '\0'.
Then put the index onto the INDEX_STREAM. */
so we skip it here. */
bp_pack_value (bp, TREE_PUBLIC (expr), 1);
}
+ else
+ bp_pack_value (bp, 0, 4);
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);
else if (TYPE_P (expr))
bp_pack_value (bp, TYPE_UNSIGNED (expr), 1);
+ else
+ bp_pack_value (bp, 0, 1);
/* We write debug info two times, do not confuse the second one. */
bp_pack_value (bp, TYPE_P (expr) ? 0 : TREE_ASM_WRITTEN (expr), 1);
bp_pack_value (bp, TREE_NO_WARNING (expr), 1);
bp_pack_value (bp, TREE_DEPRECATED (expr), 1);
if (TYPE_P (expr))
bp_pack_value (bp, TYPE_SATURATING (expr), 1);
- if (TREE_CODE (expr) == SSA_NAME)
+ else if (TREE_CODE (expr) == SSA_NAME)
bp_pack_value (bp, SSA_NAME_IS_DEFAULT_DEF (expr), 1);
+ else
+ bp_pack_value (bp, 0, 1);
}
struct fixed_value fv = TREE_FIXED_CST (expr);
bp_pack_value (bp, fv.data.low, HOST_BITS_PER_WIDE_INT);
bp_pack_value (bp, fv.data.high, HOST_BITS_PER_WIDE_INT);
+ bp_pack_value (bp, fv.mode, HOST_BITS_PER_INT);
}
static void
pack_ts_type_value_fields (struct bitpack_d *bp, tree expr)
{
- bp_pack_value (bp, TYPE_PRECISION (expr), 9);
- bp_pack_value (bp, TYPE_MODE (expr), 7);
+ bp_pack_value (bp, TYPE_PRECISION (expr), 10);
+ bp_pack_value (bp, TYPE_MODE (expr), 8);
bp_pack_value (bp, TYPE_STRING_FLAG (expr), 1);
bp_pack_value (bp, TYPE_NO_FORCE_BLK (expr), 1);
- bp_pack_value (bp, TYPE_NEEDS_CONSTRUCTING(expr), 1);
- if (TREE_CODE (expr) == UNION_TYPE || TREE_CODE (expr) == RECORD_TYPE)
+ bp_pack_value (bp, TYPE_NEEDS_CONSTRUCTING (expr), 1);
+ if (RECORD_OR_UNION_TYPE_P (expr))
bp_pack_value (bp, TYPE_TRANSPARENT_AGGR (expr), 1);
bp_pack_value (bp, TYPE_PACKED (expr), 1);
bp_pack_value (bp, TYPE_RESTRICT (expr), 1);
/* Pack all the non-pointer fields in EXPR into a bit pack. */
-static struct bitpack_d *
-pack_value_fields (tree expr)
+static void
+pack_value_fields (struct bitpack_d *bp, tree expr)
{
enum tree_code code;
- struct bitpack_d *bp;
code = TREE_CODE (expr);
- bp = bitpack_create ();
/* Note that all these functions are highly sensitive to changes in
the types and sizes of each of the fields being packed. */
/* This is only used by High GIMPLE. */
gcc_unreachable ();
}
-
- return bp;
}
lto_output_tree_or_ref (ob, DECL_SIZE_UNIT (expr), ref_p);
if (TREE_CODE (expr) != FUNCTION_DECL)
- lto_output_tree_or_ref (ob, DECL_INITIAL (expr), ref_p);
+ {
+ tree initial = DECL_INITIAL (expr);
+ if (TREE_CODE (expr) == VAR_DECL
+ && (TREE_STATIC (expr) || DECL_EXTERNAL (expr))
+ && initial)
+ {
+ lto_varpool_encoder_t varpool_encoder = ob->decl_state->varpool_node_encoder;
+ struct varpool_node *vnode = varpool_get_node (expr);
+ if (!vnode)
+ initial = error_mark_node;
+ else if (!lto_varpool_encoder_encode_initializer_p (varpool_encoder,
+ vnode))
+ initial = NULL;
+ }
+
+ lto_output_tree_or_ref (ob, initial, ref_p);
+ }
lto_output_tree_or_ref (ob, DECL_ATTRIBUTES (expr), ref_p);
lto_output_tree_or_ref (ob, DECL_ABSTRACT_ORIGIN (expr), ref_p);
lto_output_tree_or_ref (ob, TYPE_VALUES (expr), ref_p);
else if (TREE_CODE (expr) == ARRAY_TYPE)
lto_output_tree_or_ref (ob, TYPE_DOMAIN (expr), ref_p);
- else if (TREE_CODE (expr) == RECORD_TYPE || TREE_CODE (expr) == UNION_TYPE)
+ else if (RECORD_OR_UNION_TYPE_P (expr))
lto_output_tree_or_ref (ob, TYPE_FIELDS (expr), ref_p);
- else if (TREE_CODE (expr) == FUNCTION_TYPE || TREE_CODE (expr) == METHOD_TYPE)
+ else if (TREE_CODE (expr) == FUNCTION_TYPE
+ || TREE_CODE (expr) == METHOD_TYPE)
lto_output_tree_or_ref (ob, TYPE_ARG_TYPES (expr), ref_p);
else if (TREE_CODE (expr) == VECTOR_TYPE)
lto_output_tree_or_ref (ob, TYPE_DEBUG_REPRESENTATION_TYPE (expr), ref_p);
lto_output_tree_or_ref (ob, TYPE_MAIN_VARIANT (expr), ref_p);
/* Do not stream TYPE_NEXT_VARIANT, we reconstruct the variant lists
during fixup. */
- if (TREE_CODE (expr) == RECORD_TYPE || TREE_CODE (expr) == UNION_TYPE)
+ if (RECORD_OR_UNION_TYPE_P (expr))
lto_output_tree_or_ref (ob, TYPE_BINFO (expr), ref_p);
lto_output_tree_or_ref (ob, TYPE_CONTEXT (expr), ref_p);
- lto_output_tree_or_ref (ob, TYPE_CANONICAL (expr), ref_p);
+ /* TYPE_CANONICAL is re-computed during type merging, so no need
+ to stream it here. */
lto_output_tree_or_ref (ob, TYPE_STUB_DECL (expr), ref_p);
}
static void
lto_write_tree (struct output_block *ob, tree expr, bool ref_p, int ix)
{
- struct bitpack_d *bp;
+ struct bitpack_d bp;
/* Write the header, containing everything needed to materialize
EXPR on the reading side. */
/* Pack all the non-pointer fields in EXPR into a bitpack and write
the resulting bitpack. */
- bp = pack_value_fields (expr);
- lto_output_bitpack (ob->main_stream, bp);
- bitpack_delete (bp);
+ bp = bitpack_create (ob->main_stream);
+ pack_value_fields (&bp, expr);
+ lto_output_bitpack (&bp);
/* Write all the pointer fields in EXPR. */
lto_output_tree_pointers (ob, expr, ref_p);
unsigned i;
enum gimple_code code;
enum LTO_tags tag;
- struct bitpack_d *bp;
+ struct bitpack_d bp;
/* Emit identifying tag. */
code = gimple_code (stmt);
output_record_start (ob, tag);
/* Emit the tuple header. */
- bp = bitpack_create ();
- bp_pack_value (bp, gimple_num_ops (stmt), sizeof (unsigned) * 8);
- bp_pack_value (bp, gimple_no_warning_p (stmt), 1);
+ bp = bitpack_create (ob->main_stream);
+ bp_pack_value (&bp, gimple_num_ops (stmt), sizeof (unsigned) * 8);
+ bp_pack_value (&bp, gimple_no_warning_p (stmt), 1);
if (is_gimple_assign (stmt))
- bp_pack_value (bp, gimple_assign_nontemporal_move_p (stmt), 1);
- bp_pack_value (bp, gimple_has_volatile_ops (stmt), 1);
- bp_pack_value (bp, stmt->gsbase.subcode, 16);
- lto_output_bitpack (ob->main_stream, bp);
- bitpack_delete (bp);
+ bp_pack_value (&bp, gimple_assign_nontemporal_move_p (stmt), 1);
+ bp_pack_value (&bp, gimple_has_volatile_ops (stmt), 1);
+ bp_pack_value (&bp, stmt->gsbase.subcode, 16);
+ lto_output_bitpack (&bp);
/* Emit location information for the statement. */
lto_output_location (ob, gimple_location (stmt));
lto_output_uleb128_stream (ob->main_stream, gimple_asm_ninputs (stmt));
lto_output_uleb128_stream (ob->main_stream, gimple_asm_noutputs (stmt));
lto_output_uleb128_stream (ob->main_stream, gimple_asm_nclobbers (stmt));
+ lto_output_uleb128_stream (ob->main_stream, gimple_asm_nlabels (stmt));
output_string (ob, ob->main_stream, gimple_asm_string (stmt));
/* Fallthru */
for (i = 0; i < gimple_num_ops (stmt); i++)
{
tree op = gimple_op (stmt, i);
+ /* Wrap all uses of non-automatic variables inside MEM_REFs
+ so that we do not have to deal with type mismatches on
+ merged symbols during IL read in. */
+ if (op)
+ {
+ tree *basep = &op;
+ if (handled_component_p (*basep))
+ basep = &TREE_OPERAND (*basep, 0);
+ if (TREE_CODE (*basep) == VAR_DECL
+ && !auto_var_in_fn_p (*basep, current_function_decl))
+ {
+ bool volatilep = TREE_THIS_VOLATILE (*basep);
+ *basep = build2 (MEM_REF, TREE_TYPE (*basep),
+ build_fold_addr_expr (*basep),
+ build_int_cst (build_pointer_type
+ (TREE_TYPE (*basep)), 0));
+ TREE_THIS_VOLATILE (*basep) = volatilep;
+ }
+ }
lto_output_tree_ref (ob, op);
}
break;
if (section_type == LTO_section_function_body)
{
const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fn));
- section_name = lto_get_section_name (section_type, name);
+ section_name = lto_get_section_name (section_type, name, NULL);
}
else
- section_name = lto_get_section_name (section_type, NULL);
+ section_name = lto_get_section_name (section_type, NULL, NULL);
lto_begin_section (section_name, !flag_wpa);
free (section_name);
static void
output_function (struct cgraph_node *node)
{
- struct bitpack_d *bp;
+ 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);
output_record_start (ob, LTO_function);
/* Write all the attributes for FN. */
- bp = bitpack_create ();
- bp_pack_value (bp, fn->is_thunk, 1);
- bp_pack_value (bp, fn->has_local_explicit_reg_vars, 1);
- bp_pack_value (bp, fn->after_tree_profile, 1);
- bp_pack_value (bp, fn->returns_pcc_struct, 1);
- bp_pack_value (bp, fn->returns_struct, 1);
- bp_pack_value (bp, fn->always_inline_functions_inlined, 1);
- bp_pack_value (bp, fn->after_inlining, 1);
- bp_pack_value (bp, fn->dont_save_pending_sizes_p, 1);
- bp_pack_value (bp, fn->stdarg, 1);
- bp_pack_value (bp, fn->has_nonlocal_label, 1);
- bp_pack_value (bp, fn->calls_alloca, 1);
- bp_pack_value (bp, fn->calls_setjmp, 1);
- bp_pack_value (bp, fn->va_list_fpr_size, 8);
- bp_pack_value (bp, fn->va_list_gpr_size, 8);
- lto_output_bitpack (ob->main_stream, bp);
- bitpack_delete (bp);
+ bp = bitpack_create (ob->main_stream);
+ bp_pack_value (&bp, fn->is_thunk, 1);
+ bp_pack_value (&bp, fn->has_local_explicit_reg_vars, 1);
+ bp_pack_value (&bp, fn->after_tree_profile, 1);
+ bp_pack_value (&bp, fn->returns_pcc_struct, 1);
+ bp_pack_value (&bp, fn->returns_struct, 1);
+ bp_pack_value (&bp, fn->can_throw_non_call_exceptions, 1);
+ bp_pack_value (&bp, fn->always_inline_functions_inlined, 1);
+ bp_pack_value (&bp, fn->after_inlining, 1);
+ bp_pack_value (&bp, fn->dont_save_pending_sizes_p, 1);
+ bp_pack_value (&bp, fn->stdarg, 1);
+ bp_pack_value (&bp, fn->has_nonlocal_label, 1);
+ bp_pack_value (&bp, fn->calls_alloca, 1);
+ bp_pack_value (&bp, fn->calls_setjmp, 1);
+ bp_pack_value (&bp, fn->va_list_fpr_size, 8);
+ bp_pack_value (&bp, fn->va_list_gpr_size, 8);
+ lto_output_bitpack (&bp);
/* Output current IL state of the function. */
output_uleb128 (ob, fn->curr_properties);
lto_output_tree_ref (ob, fn->nonlocal_goto_save_area);
/* Output all the local variables in the function. */
- lto_output_tree_ref (ob, fn->local_decls);
+ output_sleb128 (ob, VEC_length (tree, fn->local_decls));
+ for (i = 0; VEC_iterate (tree, fn->local_decls, i, t); i++)
+ lto_output_tree_ref (ob, t);
/* Output the head of the arguments list. */
lto_output_tree_ref (ob, DECL_ARGUMENTS (function));
the file processed by LTRANS. */
static bool
-output_alias_pair_p (alias_pair *p, cgraph_node_set set)
+output_alias_pair_p (alias_pair *p, cgraph_node_set set, varpool_node_set vset)
{
- cgraph_node_set_iterator csi;
- struct cgraph_node *target_node;
-
- /* Always emit VAR_DECLs. FIXME lto, we should probably only emit
- those VAR_DECLs that are instantiated in this file partition, but
- we have no easy way of knowing this based on SET. */
if (TREE_CODE (p->decl) == VAR_DECL)
- return true;
+ return varpool_node_in_set_p (varpool_node_for_asm (p->target), vset);
/* Check if the assembler name for P->TARGET has its cgraph node in SET. */
gcc_assert (TREE_CODE (p->decl) == FUNCTION_DECL);
- target_node = cgraph_node_for_asm (p->target);
- csi = cgraph_node_set_find (set, target_node);
- return (!csi_end_p (csi));
+ return cgraph_node_in_set_p (cgraph_node_for_asm (p->target), set);
}
and labels. */
static void
-output_unreferenced_globals (cgraph_node_set set)
+output_unreferenced_globals (cgraph_node_set set, varpool_node_set vset)
{
struct output_block *ob;
alias_pair *p;
symbols at link time if a file defines a global symbol but
never references it. */
FOR_EACH_STATIC_VARIABLE (vnode)
- {
- tree var = vnode->decl;
-
- if (TREE_CODE (var) == VAR_DECL)
- {
- struct varpool_node *alias;
-
- /* Output the object in order to output references used in the
- initialization. */
- lto_output_tree (ob, var, true);
-
- /* If it is public we also need a reference to the object itself. */
- if (TREE_PUBLIC (var))
- lto_output_tree_ref (ob, var);
-
- /* Also output any extra_name aliases for this variable. */
- for (alias = vnode->extra_name; alias; alias = alias->next)
- {
- lto_output_tree (ob, alias->decl, true);
- output_record_start (ob, LTO_var_decl_alias);
- lto_output_var_decl_index (ob->decl_state, ob->main_stream,
- alias->decl);
- lto_output_var_decl_index (ob->decl_state, ob->main_stream,
- var);
- }
- }
- }
+ if (vnode->needed && varpool_node_in_set_p (vnode, vset))
+ {
+ tree var = vnode->decl;
+
+ if (TREE_CODE (var) == VAR_DECL)
+ {
+ /* Output the object in order to output references used in the
+ initialization. */
+ lto_output_tree (ob, var, true);
+
+ /* If it is public we also need a reference to the object itself. */
+ if (TREE_PUBLIC (var))
+ lto_output_tree_ref (ob, var);
+ }
+ }
output_zero (ob);
/* Emit the alias pairs for the nodes in SET. */
for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p); i++)
{
- if (output_alias_pair_p (p, set))
+ if (output_alias_pair_p (p, set, vset))
{
lto_output_tree_ref (ob, p->decl);
lto_output_tree_ref (ob, p->target);
size_t len;
const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (function));
char *section_name =
- lto_get_section_name (LTO_section_function_body, name);
+ lto_get_section_name (LTO_section_function_body, name, NULL);
size_t i, j;
struct lto_in_decl_state *in_state;
struct lto_out_decl_state *out_state = lto_get_out_decl_state ();
/* Main entry point from the pass manager. */
static void
-lto_output (cgraph_node_set set)
+lto_output (cgraph_node_set set, varpool_node_set vset)
{
struct cgraph_node *node;
struct lto_out_decl_state *decl_state;
- cgraph_node_set_iterator csi;
+#ifdef ENABLE_CHECKING
bitmap output = lto_bitmap_alloc ();
+#endif
+ int i, n_nodes;
+ lto_cgraph_encoder_t encoder = lto_get_out_decl_state ()->cgraph_node_encoder;
lto_writer_init ();
+ n_nodes = lto_cgraph_encoder_size (encoder);
/* Process only the functions with bodies. */
- for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
+ for (i = 0; i < n_nodes; i++)
{
- node = csi_node (csi);
- if (node->analyzed && !bitmap_bit_p (output, DECL_UID (node->decl)))
+ node = lto_cgraph_encoder_deref (encoder, i);
+ if (lto_cgraph_encoder_encode_body_p (encoder, node))
{
+#ifdef ENABLE_CHECKING
+ gcc_assert (!bitmap_bit_p (output, DECL_UID (node->decl)));
bitmap_set_bit (output, DECL_UID (node->decl));
+#endif
decl_state = lto_new_out_decl_state ();
lto_push_out_decl_state (decl_state);
if (!flag_wpa)
be done now to make sure that all the statements in every function
have been renumbered so that edges can be associated with call
statements using the statement UIDs. */
- output_cgraph (set);
+ output_cgraph (set, vset);
+#ifdef ENABLE_CHECKING
lto_bitmap_free (output);
+#endif
}
struct ipa_opt_pass_d pass_ipa_lto_gimple_out =
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
- TV_IPA_LTO_GIMPLE_IO, /* tv_id */
+ TV_IPA_LTO_GIMPLE_OUT, /* tv_id */
0, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
t = lto_tree_ref_encoder_get_tree (encoder, index);
if (!lto_streamer_cache_lookup (ob->writer_cache, t, NULL))
lto_output_tree (ob, t, false);
-
- if (flag_wpa)
- {
- /* In WPA we should not emit multiple definitions of the
- same symbol to all the files in the link set. If
- T had already been emitted as the pervailing definition
- in one file, do not emit it in the others. */
- /* FIXME lto. We should check if T belongs to the
- file we are writing to. */
- if (TREE_CODE (t) == VAR_DECL
- && TREE_PUBLIC (t)
- && !DECL_EXTERNAL (t))
- TREE_ASM_WRITTEN (t) = 1;
- }
}
}
}
-/* Helper function of write_symbols_of_kind. CACHE is the streamer
- cache with all the pickled nodes. STREAM is the stream where to
- write the table. V is a vector with the DECLs that should be on
- the table. SEEN is a bitmap of symbols written so far. */
+/* Write symbol T into STREAM in CACHE. SEEN specify symbols we wrote so
+ far. */
static void
-write_symbol_vec (struct lto_streamer_cache_d *cache,
- struct lto_output_stream *stream,
- VEC(tree,heap) *v, bitmap seen)
+write_symbol (struct lto_streamer_cache_d *cache,
+ struct lto_output_stream *stream,
+ tree t, bitmap seen, bool alias)
{
- tree t;
- int index;
-
- for (index = 0; VEC_iterate(tree, v, index, t); index++)
- {
- const char *name;
- enum gcc_plugin_symbol_kind kind;
- enum gcc_plugin_symbol_visibility visibility;
- int slot_num;
- uint64_t size;
- const char *comdat;
-
- /* None of the following kinds of symbols are needed in the
- symbol table. */
- if (!TREE_PUBLIC (t)
- || is_builtin_fn (t)
- || DECL_ABSTRACT (t)
- || TREE_CODE (t) == RESULT_DECL)
- continue;
+ const char *name;
+ enum gcc_plugin_symbol_kind kind;
+ enum gcc_plugin_symbol_visibility visibility;
+ int slot_num;
+ uint64_t size;
+ const char *comdat;
- gcc_assert (TREE_CODE (t) == VAR_DECL
- || TREE_CODE (t) == FUNCTION_DECL);
+ /* None of the following kinds of symbols are needed in the
+ symbol table. */
+ if (!TREE_PUBLIC (t)
+ || is_builtin_fn (t)
+ || DECL_ABSTRACT (t)
+ || TREE_CODE (t) == RESULT_DECL)
+ return;
- name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (t));
+ gcc_assert (TREE_CODE (t) == VAR_DECL
+ || TREE_CODE (t) == FUNCTION_DECL);
- /* FIXME lto: this is from assemble_name_raw in varasm.c. For some
- architectures we might have to do the same name manipulations that
- ASM_OUTPUT_LABELREF does. */
- if (name[0] == '*')
- name = &name[1];
+ name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (t));
- lto_streamer_cache_lookup (cache, t, &slot_num);
- gcc_assert (slot_num >= 0);
+ /* FIXME lto: this is from assemble_name_raw in varasm.c. For some
+ architectures we might have to do the same name manipulations that
+ ASM_OUTPUT_LABELREF does. */
+ if (name[0] == '*')
+ name = &name[1];
- /* Avoid duplicate symbols. */
- if (bitmap_bit_p (seen, slot_num))
- continue;
- else
- bitmap_set_bit (seen, slot_num);
-
- if (DECL_EXTERNAL (t))
- {
- if (DECL_WEAK (t))
- kind = GCCPK_WEAKUNDEF;
- else
- kind = GCCPK_UNDEF;
- }
- else
- {
- if (DECL_WEAK (t))
- kind = GCCPK_WEAKDEF;
- else if (DECL_COMMON (t))
- kind = GCCPK_COMMON;
- else
- kind = GCCPK_DEF;
- }
+ lto_streamer_cache_lookup (cache, t, &slot_num);
+ gcc_assert (slot_num >= 0);
- switch (DECL_VISIBILITY(t))
- {
- case VISIBILITY_DEFAULT:
- visibility = GCCPV_DEFAULT;
- break;
- case VISIBILITY_PROTECTED:
- visibility = GCCPV_PROTECTED;
- break;
- case VISIBILITY_HIDDEN:
- visibility = GCCPV_HIDDEN;
- break;
- case VISIBILITY_INTERNAL:
- visibility = GCCPV_INTERNAL;
- break;
- }
+ /* Avoid duplicate symbols. */
+ if (bitmap_bit_p (seen, slot_num))
+ return;
+ else
+ bitmap_set_bit (seen, slot_num);
- if (kind == GCCPK_COMMON
- && DECL_SIZE (t)
- && TREE_CODE (DECL_SIZE (t)) == INTEGER_CST)
- size = (((uint64_t) TREE_INT_CST_HIGH (DECL_SIZE (t))) << 32)
- | TREE_INT_CST_LOW (DECL_SIZE (t));
+ if (DECL_EXTERNAL (t))
+ {
+ if (DECL_WEAK (t))
+ kind = GCCPK_WEAKUNDEF;
else
- size = 0;
-
- if (DECL_ONE_ONLY (t))
- comdat = IDENTIFIER_POINTER (DECL_COMDAT_GROUP (t));
+ kind = GCCPK_UNDEF;
+ }
+ else
+ {
+ if (DECL_WEAK (t))
+ kind = GCCPK_WEAKDEF;
+ else if (DECL_COMMON (t))
+ kind = GCCPK_COMMON;
else
- comdat = "";
-
- lto_output_data_stream (stream, name, strlen (name) + 1);
- lto_output_data_stream (stream, comdat, strlen (comdat) + 1);
- lto_output_data_stream (stream, &kind, 1);
- lto_output_data_stream (stream, &visibility, 1);
- lto_output_data_stream (stream, &size, 8);
- lto_output_data_stream (stream, &slot_num, 4);
+ kind = GCCPK_DEF;
+
+ /* When something is defined, it should have a node attached.
+ FIXME: For fortran this is still not the case since wrapup global
+ decls is done after streaming. */
+ gcc_assert (alias || TREE_CODE (t) != FUNCTION_DECL
+ || (cgraph_get_node (t)
+ && cgraph_get_node (t)->analyzed));
}
-}
-
-
-/* Write IL symbols of KIND. CACHE is the streamer cache with all the
- pickled nodes. SEEN is a bitmap of symbols written so far. */
-
-static void
-write_symbols_of_kind (lto_decl_stream_e_t kind,
- struct lto_streamer_cache_d *cache, bitmap seen)
-{
- struct lto_out_decl_state *out_state;
- struct lto_output_stream stream;
- unsigned num_fns =
- VEC_length (lto_out_decl_state_ptr, lto_function_decl_states);
- unsigned idx;
- memset (&stream, 0, sizeof (stream));
- out_state = lto_get_out_decl_state ();
- write_symbol_vec (cache, &stream, out_state->streams[kind].trees, seen);
-
- for (idx = 0; idx < num_fns; idx++)
+ switch (DECL_VISIBILITY(t))
{
- out_state =
- VEC_index (lto_out_decl_state_ptr, lto_function_decl_states, idx);
- write_symbol_vec (cache, &stream, out_state->streams[kind].trees, seen);
+ case VISIBILITY_DEFAULT:
+ visibility = GCCPV_DEFAULT;
+ break;
+ case VISIBILITY_PROTECTED:
+ visibility = GCCPV_PROTECTED;
+ break;
+ case VISIBILITY_HIDDEN:
+ visibility = GCCPV_HIDDEN;
+ break;
+ case VISIBILITY_INTERNAL:
+ visibility = GCCPV_INTERNAL;
+ break;
}
- lto_write_stream (&stream);
+ if (kind == GCCPK_COMMON
+ && DECL_SIZE (t)
+ && TREE_CODE (DECL_SIZE (t)) == INTEGER_CST)
+ size = (((uint64_t) TREE_INT_CST_HIGH (DECL_SIZE (t))) << 32)
+ | TREE_INT_CST_LOW (DECL_SIZE (t));
+ else
+ size = 0;
+
+ if (DECL_ONE_ONLY (t))
+ comdat = IDENTIFIER_POINTER (DECL_COMDAT_GROUP (t));
+ else
+ comdat = "";
+
+ lto_output_data_stream (stream, name, strlen (name) + 1);
+ lto_output_data_stream (stream, comdat, strlen (comdat) + 1);
+ lto_output_data_stream (stream, &kind, 1);
+ lto_output_data_stream (stream, &visibility, 1);
+ lto_output_data_stream (stream, &size, 8);
+ lto_output_data_stream (stream, &slot_num, 4);
}
-/* Write an IL symbol table. CACHE is the streamer cache with all the
- pickled nodes. */
+/* Write an IL symbol table to OB.
+ SET and VSET are cgraph/varpool node sets we are outputting. */
static void
-produce_symtab (struct lto_streamer_cache_d *cache)
+produce_symtab (struct output_block *ob,
+ cgraph_node_set set, varpool_node_set vset)
{
- char *section_name = lto_get_section_name (LTO_section_symtab, NULL);
+ struct lto_streamer_cache_d *cache = ob->writer_cache;
+ char *section_name = lto_get_section_name (LTO_section_symtab, NULL, NULL);
bitmap seen;
+ struct cgraph_node *node, *alias;
+ struct varpool_node *vnode, *valias;
+ struct lto_output_stream stream;
+ lto_varpool_encoder_t varpool_encoder = ob->decl_state->varpool_node_encoder;
+ lto_cgraph_encoder_t encoder = ob->decl_state->cgraph_node_encoder;
+ int i;
+ alias_pair *p;
lto_begin_section (section_name, false);
free (section_name);
seen = lto_bitmap_alloc ();
- write_symbols_of_kind (LTO_DECL_STREAM_FN_DECL, cache, seen);
- write_symbols_of_kind (LTO_DECL_STREAM_VAR_DECL, cache, seen);
+ memset (&stream, 0, sizeof (stream));
+
+ /* Write all functions. */
+ for (i = 0; i < lto_cgraph_encoder_size (encoder); i++)
+ {
+ node = lto_cgraph_encoder_deref (encoder, i);
+ if (node->alias)
+ continue;
+ write_symbol (cache, &stream, node->decl, seen, false);
+ for (alias = node->same_body; alias; alias = alias->next)
+ write_symbol (cache, &stream, alias->decl, seen, true);
+ }
+
+ /* Write all variables. */
+ for (i = 0; i < lto_varpool_encoder_size (varpool_encoder); i++)
+ {
+ vnode = lto_varpool_encoder_deref (varpool_encoder, i);
+ if (vnode->alias)
+ continue;
+ write_symbol (cache, &stream, vnode->decl, seen, false);
+ for (valias = vnode->extra_name; valias; valias = valias->next)
+ write_symbol (cache, &stream, valias->decl, seen, true);
+ }
+
+ /* Write all aliases. */
+ for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p); i++)
+ if (output_alias_pair_p (p, set, vset))
+ write_symbol (cache, &stream, p->decl, seen, true);
+
+ lto_write_stream (&stream);
lto_bitmap_free (seen);
lto_end_section ();
recover these on other side. */
static void
-produce_asm_for_decls (cgraph_node_set set)
+produce_asm_for_decls (cgraph_node_set set, varpool_node_set vset)
{
struct lto_out_decl_state *out_state;
struct lto_out_decl_state *fn_out_state;
/* Write out unreferenced globals, alias pairs and labels. We defer
doing this until now so that we can write out only what is
needed. */
- output_unreferenced_globals (set);
+ output_unreferenced_globals (set, vset);
memset (&header, 0, sizeof (struct lto_decl_header));
- section_name = lto_get_section_name (LTO_section_decls, NULL);
+ section_name = lto_get_section_name (LTO_section_decls, NULL, NULL);
lto_begin_section (section_name, !flag_wpa);
free (section_name);
lto_end_section ();
- /* Write the symbol table. */
- produce_symtab (ob->writer_cache);
+ /* Write the symbol table. It is used by linker to determine dependencies
+ and thus we can skip it for WPA. */
+ if (!flag_wpa)
+ produce_symtab (ob, set, vset);
/* Write command line opts. */
lto_write_options ();
/* Deallocate memory and clean up. */
+ for (idx = 0; idx < num_fns; idx++)
+ {
+ fn_out_state =
+ VEC_index (lto_out_decl_state_ptr, lto_function_decl_states, idx);
+ lto_delete_out_decl_state (fn_out_state);
+ }
lto_cgraph_encoder_delete (ob->decl_state->cgraph_node_encoder);
+ lto_varpool_encoder_delete (ob->decl_state->varpool_node_encoder);
VEC_free (lto_out_decl_state_ptr, heap, lto_function_decl_states);
lto_function_decl_states = NULL;
destroy_output_block (ob);
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
- TV_IPA_LTO_DECL_IO, /* tv_id */
+ TV_IPA_LTO_DECL_OUT, /* tv_id */
0, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */