summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog33
-rw-r--r--gcc/cgraph.h2
-rw-r--r--gcc/ipa-prop.c4
-rw-r--r--gcc/ipa-visibility.c2
-rw-r--r--gcc/lto-cgraph.c4
-rw-r--r--gcc/lto-streamer-in.c67
-rw-r--r--gcc/lto-streamer-out.c75
-rw-r--r--gcc/lto-streamer.h7
-rw-r--r--gcc/lto/ChangeLog6
-rw-r--r--gcc/lto/lto-partition.c2
-rw-r--r--gcc/lto/lto.c2
-rw-r--r--gcc/varpool.c169
12 files changed, 282 insertions, 91 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8bc3edffb98..e0995ce5395 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,38 @@
2014-07-11 Jan Hubicka <hubicka@ucw.cz>
+ * vapool.c: Include tree-ssa-alias.h, gimple.h and lto-streamer.h
+ (varpool_get_constructor): New function.
+ (varpool_ctor_useable_for_folding_p): Break out from ...
+ (ctor_for_folding): ... here; use varpool_get_constructor.
+ (varpool_assemble_decl): Likewise.
+ * lto-streamer.h (struct output_block): Turn cgraph_node
+ to symbol filed.
+ (lto_input_variable_constructor): Declare.
+ * ipa-visibility.c (function_and_variable_visibility): Use
+ varpool_get_constructor.
+ * cgraph.h (varpool_get_constructor): Declare.
+ (varpool_ctor_useable_for_folding_p): New function.
+ * lto-streamer-out.c (get_symbol_initial_value): Take encoder
+ parameter; return error_mark_node for non-trivial constructors.
+ (lto_write_tree_1, DFS_write_tree): UPdate use of
+ get_symbol_initial_value.
+ (output_function): Update initialization of symbol.
+ (output_constructor): New function.
+ (copy_function): Rename to ..
+ (copy_function_or_variable): ... this one; handle vars too.
+ (lto_output): Output variable sections.
+ * lto-streamer-in.c (input_constructor): New function.
+ (lto_read_body): Rename from ...
+ (lto_read_body_or_constructor): ... this one; handle vars
+ too.
+ (lto_input_variable_constructor): New function.
+ * ipa-prop.c (ipa_prop_write_jump_functions,
+ ipa_prop_write_all_agg_replacement): Update.
+ * lto-cgraph.c (compute_ltrans_boundary): Use it.
+ (output_cgraph_opt_summary): Set symbol to NULL.
+
+2014-07-11 Jan Hubicka <hubicka@ucw.cz>
+
* ipa-prop.c (ipa_binfo_from_known_type_jfunc): In LTO do not walk
non-polymorphic types.
* ipa-cp.c (ipa_get_jf_ancestor_result): Likewise.
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 3ab051615e3..9ef7bdfe124 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -1134,6 +1134,7 @@ void varpool_analyze_node (varpool_node *);
varpool_node * varpool_extra_name_alias (tree, tree);
varpool_node * varpool_create_variable_alias (tree, tree);
void varpool_reset_queue (void);
+bool varpool_ctor_useable_for_folding_p (varpool_node *);
tree ctor_for_folding (tree);
bool varpool_for_node_and_aliases (varpool_node *,
bool (*) (varpool_node *, void *),
@@ -1142,6 +1143,7 @@ void varpool_add_new_variable (tree);
void symtab_initialize_asm_name_hash (void);
void symtab_prevail_in_asm_name_hash (symtab_node *node);
void varpool_remove_initializer (varpool_node *);
+tree varpool_get_constructor (struct varpool_node *node);
/* In cgraph.c */
extern void change_decl_assembler_name (tree, tree);
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index 9ed9e5b82ad..40f696bf960 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -4848,7 +4848,7 @@ ipa_prop_write_jump_functions (void)
ob = create_output_block (LTO_section_jump_functions);
encoder = ob->decl_state->symtab_node_encoder;
- ob->cgraph_node = NULL;
+ ob->symbol = NULL;
for (lsei = lsei_start_function_in_partition (encoder); !lsei_end_p (lsei);
lsei_next_function_in_partition (&lsei))
{
@@ -5024,7 +5024,7 @@ ipa_prop_write_all_agg_replacement (void)
ob = create_output_block (LTO_section_ipcp_transform);
encoder = ob->decl_state->symtab_node_encoder;
- ob->cgraph_node = NULL;
+ ob->symbol = NULL;
for (lsei = lsei_start_function_in_partition (encoder); !lsei_end_p (lsei);
lsei_next_function_in_partition (&lsei))
{
diff --git a/gcc/ipa-visibility.c b/gcc/ipa-visibility.c
index e3ab005762c..3fed3455b67 100644
--- a/gcc/ipa-visibility.c
+++ b/gcc/ipa-visibility.c
@@ -686,6 +686,8 @@ function_and_variable_visibility (bool whole_program)
if (found)
{
struct pointer_set_t *visited_nodes = pointer_set_create ();
+
+ varpool_get_constructor (vnode);
walk_tree (&DECL_INITIAL (vnode->decl),
update_vtable_references, NULL, visited_nodes);
pointer_set_destroy (visited_nodes);
diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
index af480bcaea2..a1ee77b5a83 100644
--- a/gcc/lto-cgraph.c
+++ b/gcc/lto-cgraph.c
@@ -867,7 +867,7 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
{
if (!lto_symtab_encoder_encode_initializer_p (encoder,
vnode)
- && ctor_for_folding (vnode->decl) != error_mark_node)
+ && varpool_ctor_useable_for_folding_p (vnode))
{
lto_set_symtab_encoder_encode_initializer (encoder, vnode);
add_references (encoder, vnode);
@@ -1808,7 +1808,7 @@ output_cgraph_opt_summary (void)
struct output_block *ob = create_output_block (LTO_section_cgraph_opt_sum);
unsigned count = 0;
- ob->cgraph_node = NULL;
+ ob->symbol = NULL;
encoder = ob->decl_state->symtab_node_encoder;
n_nodes = lto_symtab_encoder_size (encoder);
for (i = 0; i < n_nodes; i++)
diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
index 5d7989353fe..7c22183b519 100644
--- a/gcc/lto-streamer-in.c
+++ b/gcc/lto-streamer-in.c
@@ -1029,6 +1029,15 @@ input_function (tree fn_decl, struct data_in *data_in,
pop_cfun ();
}
+/* Read the body of function FN_DECL from DATA_IN using input block IB. */
+
+static void
+input_constructor (tree var, struct data_in *data_in,
+ struct lto_input_block *ib)
+{
+ DECL_INITIAL (var) = stream_read_tree (ib, data_in);
+}
+
/* Read the body from DATA for function NODE and fill it in.
FILE_DATA are the global decls and types. SECTION_TYPE is either
@@ -1037,8 +1046,8 @@ input_function (tree fn_decl, struct data_in *data_in,
that function. */
static void
-lto_read_body (struct lto_file_decl_data *file_data, struct cgraph_node *node,
- const char *data, enum lto_section_type section_type)
+lto_read_body_or_constructor (struct lto_file_decl_data *file_data, struct symtab_node *node,
+ const char *data, enum lto_section_type section_type)
{
const struct lto_function_header *header;
struct data_in *data_in;
@@ -1050,19 +1059,32 @@ lto_read_body (struct lto_file_decl_data *file_data, struct cgraph_node *node,
tree fn_decl = node->decl;
header = (const struct lto_function_header *) data;
- cfg_offset = sizeof (struct lto_function_header);
- main_offset = cfg_offset + header->cfg_size;
- string_offset = main_offset + header->main_size;
-
- LTO_INIT_INPUT_BLOCK (ib_cfg,
- data + cfg_offset,
- 0,
- header->cfg_size);
+ if (TREE_CODE (node->decl) == FUNCTION_DECL)
+ {
+ cfg_offset = sizeof (struct lto_function_header);
+ main_offset = cfg_offset + header->cfg_size;
+ string_offset = main_offset + header->main_size;
+
+ LTO_INIT_INPUT_BLOCK (ib_cfg,
+ data + cfg_offset,
+ 0,
+ header->cfg_size);
+
+ LTO_INIT_INPUT_BLOCK (ib_main,
+ data + main_offset,
+ 0,
+ header->main_size);
+ }
+ else
+ {
+ main_offset = sizeof (struct lto_function_header);
+ string_offset = main_offset + header->main_size;
- LTO_INIT_INPUT_BLOCK (ib_main,
- data + main_offset,
- 0,
- header->main_size);
+ LTO_INIT_INPUT_BLOCK (ib_main,
+ data + main_offset,
+ 0,
+ header->main_size);
+ }
data_in = lto_data_in_create (file_data, data + string_offset,
header->string_size, vNULL);
@@ -1082,7 +1104,10 @@ lto_read_body (struct lto_file_decl_data *file_data, struct cgraph_node *node,
/* Set up the struct function. */
from = data_in->reader_cache->nodes.length ();
- input_function (fn_decl, data_in, &ib_main, &ib_cfg);
+ if (TREE_CODE (node->decl) == FUNCTION_DECL)
+ input_function (fn_decl, data_in, &ib_main, &ib_cfg);
+ else
+ input_constructor (fn_decl, data_in, &ib_main);
/* And fixup types we streamed locally. */
{
struct streamer_tree_cache_d *cache = data_in->reader_cache;
@@ -1124,7 +1149,17 @@ void
lto_input_function_body (struct lto_file_decl_data *file_data,
struct cgraph_node *node, const char *data)
{
- lto_read_body (file_data, node, data, LTO_section_function_body);
+ lto_read_body_or_constructor (file_data, node, data, LTO_section_function_body);
+}
+
+/* Read the body of NODE using DATA. FILE_DATA holds the global
+ decls and types. */
+
+void
+lto_input_variable_constructor (struct lto_file_decl_data *file_data,
+ struct varpool_node *node, const char *data)
+{
+ lto_read_body_or_constructor (file_data, node, data, LTO_section_function_body);
}
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index bd289090bae..4a94fcda185 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -318,7 +318,7 @@ lto_is_streamable (tree expr)
/* For EXPR lookup and return what we want to stream to OB as DECL_INITIAL. */
static tree
-get_symbol_initial_value (struct output_block *ob, tree expr)
+get_symbol_initial_value (lto_symtab_encoder_t encoder, tree expr)
{
gcc_checking_assert (DECL_P (expr)
&& TREE_CODE (expr) != FUNCTION_DECL
@@ -331,15 +331,13 @@ get_symbol_initial_value (struct output_block *ob, tree expr)
&& !DECL_IN_CONSTANT_POOL (expr)
&& initial)
{
- lto_symtab_encoder_t encoder;
varpool_node *vnode;
-
- encoder = ob->decl_state->symtab_node_encoder;
- vnode = varpool_get_node (expr);
- if (!vnode
- || !lto_symtab_encoder_encode_initializer_p (encoder,
- vnode))
- initial = error_mark_node;
+ /* Extra section needs about 30 bytes; do not produce it for simple
+ scalar values. */
+ if (TREE_CODE (DECL_INITIAL (expr)) == CONSTRUCTOR
+ || !(vnode = varpool_get_node (expr))
+ || !lto_symtab_encoder_encode_initializer_p (encoder, vnode))
+ initial = error_mark_node;
}
return initial;
@@ -369,7 +367,8 @@ lto_write_tree_1 (struct output_block *ob, tree expr, bool ref_p)
&& TREE_CODE (expr) != TRANSLATION_UNIT_DECL)
{
/* Handle DECL_INITIAL for symbols. */
- tree initial = get_symbol_initial_value (ob, expr);
+ tree initial = get_symbol_initial_value
+ (ob->decl_state->symtab_node_encoder, expr);
stream_write_tree (ob, initial, ref_p);
}
}
@@ -1195,7 +1194,8 @@ DFS_write_tree (struct output_block *ob, sccs *from_state,
&& TREE_CODE (expr) != TRANSLATION_UNIT_DECL)
{
/* Handle DECL_INITIAL for symbols. */
- tree initial = get_symbol_initial_value (ob, expr);
+ tree initial = get_symbol_initial_value (ob->decl_state->symtab_node_encoder,
+ expr);
DFS_write_tree (ob, cstate, initial, ref_p, ref_p);
}
}
@@ -1808,7 +1808,7 @@ output_function (struct cgraph_node *node)
ob = create_output_block (LTO_section_function_body);
clear_line_info (ob);
- ob->cgraph_node = node;
+ ob->symbol = node;
gcc_assert (current_function_decl == NULL_TREE && cfun == NULL);
@@ -1899,6 +1899,32 @@ output_function (struct cgraph_node *node)
destroy_output_block (ob);
}
+/* Output the body of function NODE->DECL. */
+
+static void
+output_constructor (struct varpool_node *node)
+{
+ tree var = node->decl;
+ struct output_block *ob;
+
+ ob = create_output_block (LTO_section_function_body);
+
+ clear_line_info (ob);
+ ob->symbol = node;
+
+ /* Make string 0 be a NULL string. */
+ streamer_write_char_stream (ob->string_stream, 0);
+
+ /* Output DECL_INITIAL for the function, which contains the tree of
+ lexical scopes. */
+ stream_write_tree (ob, DECL_INITIAL (var), true);
+
+ /* Create a section to hold the pickled output of this function. */
+ produce_asm (ob, var);
+
+ destroy_output_block (ob);
+}
+
/* Emit toplevel asms. */
@@ -1957,10 +1983,10 @@ lto_output_toplevel_asms (void)
}
-/* Copy the function body of NODE without deserializing. */
+/* Copy the function body or variable constructor of NODE without deserializing. */
static void
-copy_function (struct cgraph_node *node)
+copy_function_or_variable (struct symtab_node *node)
{
tree function = node->decl;
struct lto_file_decl_data *file_data = node->lto_file_data;
@@ -2072,7 +2098,7 @@ lto_output (void)
if (gimple_has_body_p (node->decl) || !flag_wpa)
output_function (node);
else
- copy_function (node);
+ copy_function_or_variable (node);
gcc_assert (lto_get_out_decl_state () == decl_state);
lto_pop_out_decl_state ();
lto_record_function_out_decl_state (node->decl, decl_state);
@@ -2085,6 +2111,25 @@ lto_output (void)
tree ctor = DECL_INITIAL (node->decl);
if (ctor && !in_lto_p)
walk_tree (&ctor, wrap_refs, NULL, NULL);
+ if (get_symbol_initial_value (encoder, node->decl) == error_mark_node
+ && lto_symtab_encoder_encode_initializer_p (encoder, node)
+ && !node->alias)
+ {
+#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 (DECL_INITIAL (node->decl) != error_mark_node
+ || !flag_wpa)
+ output_constructor (node);
+ else
+ copy_function_or_variable (node);
+ gcc_assert (lto_get_out_decl_state () == decl_state);
+ lto_pop_out_decl_state ();
+ lto_record_function_out_decl_state (node->decl, decl_state);
+ }
}
}
diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h
index cfa965c4d1e..c6cf72c1ad3 100644
--- a/gcc/lto-streamer.h
+++ b/gcc/lto-streamer.h
@@ -685,9 +685,9 @@ struct output_block
far and the indexes assigned to them. */
hash_table<string_slot_hasher> *string_hash_table;
- /* The current cgraph_node that we are currently serializing. Null
+ /* The current symbol that we are currently serializing. Null
if we are serializing something else. */
- struct cgraph_node *cgraph_node;
+ struct symtab_node *symbol;
/* These are the last file and line that were seen in the stream.
If the current node differs from these, it needs to insert
@@ -830,6 +830,9 @@ extern void lto_reader_init (void);
extern void lto_input_function_body (struct lto_file_decl_data *,
struct cgraph_node *,
const char *);
+extern void lto_input_variable_constructor (struct lto_file_decl_data *,
+ struct varpool_node *,
+ const char *);
extern void lto_input_constructors_and_inits (struct lto_file_decl_data *,
const char *);
extern void lto_input_toplevel_asms (struct lto_file_decl_data *, int);
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index 78e32edaf95..ec78b2aa4e9 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -1,3 +1,9 @@
+2014-07-11 Jan Hubicka <hubicka@ucw.cz>
+
+ * lto-partition.c (add_references_to_partition): Use
+ varpool_ctor_useable_for_folding_p.
+ * lto.c (lto_read_in_decl_state): Update sanity check.
+
2014-07-01 Martin Liska <mliska@suse.cz>
IPA REF alias refactoring
diff --git a/gcc/lto/lto-partition.c b/gcc/lto/lto-partition.c
index 944943cf1cc..5f290353500 100644
--- a/gcc/lto/lto-partition.c
+++ b/gcc/lto/lto-partition.c
@@ -96,7 +96,7 @@ add_references_to_partition (ltrans_partition part, symtab_node *node)
Recursively look into the initializers of the constant variable and add
references, too. */
else if (is_a <varpool_node *> (ref->referred)
- && ctor_for_folding (ref->referred->decl) != error_mark_node
+ && varpool_ctor_useable_for_folding_p (varpool (ref->referred))
&& !lto_symtab_encoder_in_partition_p (part->encoder, ref->referred))
{
if (!part->initializers_visited)
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index 20b78a8c499..cdf8a7218d6 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -236,7 +236,7 @@ lto_read_in_decl_state (struct data_in *data_in, const uint32_t *data,
ix = *data++;
decl = streamer_tree_cache_get_tree (data_in->reader_cache, ix);
- if (TREE_CODE (decl) != FUNCTION_DECL)
+ if (!VAR_OR_FUNCTION_DECL_P (decl))
{
gcc_assert (decl == void_type_node);
decl = NULL_TREE;
diff --git a/gcc/varpool.c b/gcc/varpool.c
index 79f07bfd2ff..2b379ccac38 100644
--- a/gcc/varpool.c
+++ b/gcc/varpool.c
@@ -35,6 +35,9 @@ along with GCC; see the file COPYING3. If not see
#include "gimple-expr.h"
#include "flags.h"
#include "pointer-set.h"
+#include "tree-ssa-alias.h"
+#include "gimple.h"
+#include "lto-streamer.h"
const char * const tls_model_names[]={"none", "tls-emulated", "tls-real",
"tls-global-dynamic", "tls-local-dynamic",
@@ -163,19 +166,17 @@ varpool_node_for_decl (tree decl)
void
varpool_remove_node (varpool_node *node)
{
- tree init;
varpool_call_node_removal_hooks (node);
symtab_unregister_node (node);
- /* Because we remove references from external functions before final compilation,
- we may end up removing useful constructors.
- FIXME: We probably want to trace boundaries better. */
+ /* When streaming we can have multiple nodes associated with decl. */
if (cgraph_state == CGRAPH_LTO_STREAMING)
;
- else if ((init = ctor_for_folding (node->decl)) == error_mark_node)
+ /* Keep constructor when it may be used for folding. We remove
+ references to external variables before final compilation. */
+ else if (DECL_INITIAL (node->decl) && DECL_INITIAL (node->decl) != error_mark_node
+ && !varpool_ctor_useable_for_folding_p (node))
varpool_remove_initializer (node);
- else
- DECL_INITIAL (node->decl) = init;
ggc_free (node);
}
@@ -215,7 +216,7 @@ dump_varpool_node (FILE *f, varpool_node *node)
fprintf (f, " used-by-single-function");
if (TREE_READONLY (node->decl))
fprintf (f, " read-only");
- if (ctor_for_folding (node->decl) != error_mark_node)
+ if (varpool_ctor_useable_for_folding_p (node))
fprintf (f, " const-value-known");
if (node->writeonly)
fprintf (f, " write-only");
@@ -253,9 +254,101 @@ varpool_node_for_asm (tree asmname)
return NULL;
}
-/* Return if DECL is constant and its initial value is known (so we can do
- constant folding using DECL_INITIAL (decl)).
- Return ERROR_MARK_NODE when value is unknown. */
+/* When doing LTO, read NODE's constructor from disk if it is not already present. */
+
+tree
+varpool_get_constructor (struct varpool_node *node)
+{
+ struct lto_file_decl_data *file_data;
+ const char *data, *name;
+ size_t len;
+ tree decl = node->decl;
+
+ if (DECL_INITIAL (node->decl) != error_mark_node
+ || !in_lto_p)
+ return DECL_INITIAL (node->decl);
+
+ file_data = node->lto_file_data;
+ name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+
+ /* We may have renamed the declaration, e.g., a static function. */
+ name = lto_get_decl_name_mapping (file_data, name);
+
+ data = lto_get_section_data (file_data, LTO_section_function_body,
+ name, &len);
+ if (!data)
+ fatal_error ("%s: section %s is missing",
+ file_data->file_name,
+ name);
+
+ lto_input_variable_constructor (file_data, node, data);
+ lto_stats.num_function_bodies++;
+ lto_free_section_data (file_data, LTO_section_function_body, name,
+ data, len);
+ lto_free_function_in_decl_state_for_node (node);
+ return DECL_INITIAL (node->decl);
+}
+
+/* Return ture if NODE has constructor that can be used for folding. */
+
+bool
+varpool_ctor_useable_for_folding_p (varpool_node *node)
+{
+ varpool_node *real_node = node;
+
+ if (real_node->alias && real_node->definition)
+ real_node = varpool_variable_node (node);
+
+ if (TREE_CODE (node->decl) == CONST_DECL
+ || DECL_IN_CONSTANT_POOL (node->decl))
+ return true;
+ if (TREE_THIS_VOLATILE (node->decl))
+ return false;
+
+ /* If we do not have a constructor, we can't use it. */
+ if (DECL_INITIAL (real_node->decl) == error_mark_node
+ && !real_node->lto_file_data)
+ return false;
+
+ /* Vtables are defined by their types and must match no matter of interposition
+ rules. */
+ if (DECL_VIRTUAL_P (node->decl))
+ {
+ /* The C++ front end creates VAR_DECLs for vtables of typeinfo
+ classes not defined in the current TU so that it can refer
+ to them from typeinfo objects. Avoid returning NULL_TREE. */
+ return DECL_INITIAL (real_node->decl) != NULL;
+ }
+
+ /* Alias of readonly variable is also readonly, since the variable is stored
+ in readonly memory. We also accept readonly aliases of non-readonly
+ locations assuming that user knows what he is asking for. */
+ if (!TREE_READONLY (node->decl) && !TREE_READONLY (real_node->decl))
+ return false;
+
+ /* Variables declared 'const' without an initializer
+ have zero as the initializer if they may not be
+ overridden at link or run time. */
+ if (!DECL_INITIAL (real_node->decl)
+ && (DECL_EXTERNAL (node->decl) || decl_replaceable_p (node->decl)))
+ return false;
+
+ /* Variables declared `const' with an initializer are considered
+ to not be overwritable with different initializer by default.
+
+ ??? Previously we behaved so for scalar variables but not for array
+ accesses. */
+ return true;
+}
+
+/* If DECL is constant variable and its initial value is known (so we can
+ do constant folding), return its constructor (DECL_INITIAL). This may
+ be an expression or NULL when DECL is initialized to 0.
+ Return ERROR_MARK_NODE otherwise.
+
+ In LTO this may actually trigger reading the constructor from disk.
+ For this reason varpool_ctor_useable_for_folding_p should be used when
+ the actual constructor value is not needed. */
tree
ctor_for_folding (tree decl)
@@ -284,7 +377,7 @@ ctor_for_folding (tree decl)
gcc_assert (TREE_CODE (decl) == VAR_DECL);
- node = varpool_get_node (decl);
+ real_node = node = varpool_get_node (decl);
if (node)
{
real_node = varpool_variable_node (node);
@@ -302,54 +395,25 @@ ctor_for_folding (tree decl)
{
gcc_assert (!DECL_INITIAL (decl)
|| DECL_INITIAL (decl) == error_mark_node);
- if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))
+ if (node->weakref)
{
node = varpool_alias_target (node);
decl = node->decl;
}
}
- /* Vtables are defined by their types and must match no matter of interposition
- rules. */
- if (DECL_VIRTUAL_P (real_decl))
- {
- gcc_checking_assert (TREE_READONLY (real_decl));
- if (DECL_INITIAL (real_decl))
- return DECL_INITIAL (real_decl);
- else
- {
- /* The C++ front end creates VAR_DECLs for vtables of typeinfo
- classes not defined in the current TU so that it can refer
- to them from typeinfo objects. Avoid returning NULL_TREE. */
- gcc_checking_assert (!COMPLETE_TYPE_P (DECL_CONTEXT (real_decl)));
- return error_mark_node;
- }
- }
-
- /* If there is no constructor, we have nothing to do. */
- if (DECL_INITIAL (real_decl) == error_mark_node)
- return error_mark_node;
-
- /* Non-readonly alias of readonly variable is also de-facto readonly,
- because the variable itself is in readonly section.
- We also honnor READONLY flag on alias assuming that user knows
- what he is doing. */
- if (!TREE_READONLY (decl) && !TREE_READONLY (real_decl))
- return error_mark_node;
-
- /* Variables declared 'const' without an initializer
- have zero as the initializer if they may not be
- overridden at link or run time. */
- if (!DECL_INITIAL (real_decl)
- && (DECL_EXTERNAL (decl) || decl_replaceable_p (decl)))
+ if ((!DECL_VIRTUAL_P (real_decl)
+ || DECL_INITIAL (real_decl) == error_mark_node
+ || !DECL_INITIAL (real_decl))
+ && (!node || !varpool_ctor_useable_for_folding_p (node)))
return error_mark_node;
- /* Variables declared `const' with an initializer are considered
- to not be overwritable with different initializer by default.
-
- ??? Previously we behaved so for scalar variables but not for array
- accesses. */
- return DECL_INITIAL (real_decl);
+ /* OK, we can return constructor. See if we need to fetch it from disk
+ in LTO mode. */
+ if (DECL_INITIAL (real_decl) != error_mark_node
+ || !in_lto_p)
+ return DECL_INITIAL (real_decl);
+ return varpool_get_constructor (real_node);
}
/* Add the variable DECL to the varpool.
@@ -471,6 +535,7 @@ varpool_assemble_decl (varpool_node *node)
if (!node->in_other_partition
&& !DECL_EXTERNAL (decl))
{
+ varpool_get_constructor (node);
assemble_variable (decl, 0, 1, 0);
gcc_assert (TREE_ASM_WRITTEN (decl));
node->definition = true;