diff options
Diffstat (limited to 'gcc/lto-streamer-out.c')
-rw-r--r-- | gcc/lto-streamer-out.c | 291 |
1 files changed, 162 insertions, 129 deletions
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c index 6ee2eda2784..c96c13aeefe 100644 --- a/gcc/lto-streamer-out.c +++ b/gcc/lto-streamer-out.c @@ -1706,6 +1706,25 @@ output_gimple_stmt (struct output_block *ob, gimple stmt) 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; @@ -1791,10 +1810,10 @@ produce_asm (struct output_block *ob, tree fn) 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); @@ -1840,6 +1859,8 @@ output_function (struct cgraph_node *node) struct function *fn; basic_block bb; struct output_block *ob; + unsigned i; + tree t; function = node->decl; fn = DECL_STRUCT_FUNCTION (function); @@ -1886,7 +1907,9 @@ output_function (struct cgraph_node *node) 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)); @@ -2018,7 +2041,7 @@ copy_function (struct cgraph_node *node) 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 (); @@ -2132,7 +2155,7 @@ 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 */ @@ -2262,155 +2285,163 @@ lto_out_decl_state_written_size (struct lto_out_decl_state *state) } -/* 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; + const char *name; + enum gcc_plugin_symbol_kind kind; + enum gcc_plugin_symbol_visibility visibility; + int slot_num; + uint64_t size; + const char *comdat; - 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; + /* 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; - gcc_assert (TREE_CODE (t) == VAR_DECL - || TREE_CODE (t) == FUNCTION_DECL); + gcc_assert (TREE_CODE (t) == VAR_DECL + || TREE_CODE (t) == FUNCTION_DECL); - name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (t)); + name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (t)); - /* 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]; + /* 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]; - lto_streamer_cache_lookup (cache, t, &slot_num); - gcc_assert (slot_num >= 0); + lto_streamer_cache_lookup (cache, t, &slot_num); + gcc_assert (slot_num >= 0); - /* 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; - } - - 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 (); @@ -2446,7 +2477,7 @@ produce_asm_for_decls (cgraph_node_set set, varpool_node_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); @@ -2513,8 +2544,10 @@ produce_asm_for_decls (cgraph_node_set set, varpool_node_set vset) 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 (); @@ -2544,7 +2577,7 @@ struct ipa_opt_pass_d pass_ipa_lto_finish_out = 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 */ |