/* Return varpool node assigned to DECL without creating new one. */
struct varpool_node *
-varpool_get_node (tree decl)
+varpool_get_node (const_tree decl)
{
struct varpool_node key, **slot;
- gcc_assert (DECL_P (decl) && TREE_CODE (decl) != FUNCTION_DECL);
+ gcc_assert (TREE_CODE (decl) == VAR_DECL
+ && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)));
if (!varpool_hash)
return NULL;
- key.decl = decl;
+ key.decl = CONST_CAST2 (tree, const_tree, decl);
slot = (struct varpool_node **)
htab_find_slot (varpool_hash, &key, NO_INSERT);
if (!slot)
{
struct varpool_node key, *node, **slot;
- gcc_assert (DECL_P (decl) && TREE_CODE (decl) != FUNCTION_DECL);
+ gcc_assert (TREE_CODE (decl) == VAR_DECL
+ && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)));
if (!varpool_hash)
varpool_hash = htab_create_ggc (10, hash_varpool_node,
htab_find_slot (varpool_hash, &key, INSERT);
if (*slot)
return *slot;
- node = GGC_CNEW (struct varpool_node);
+ node = ggc_alloc_cleared_varpool_node ();
node->decl = decl;
node->order = cgraph_order++;
node->next = varpool_nodes;
/* Dump the variable pool to stderr. */
-void
+DEBUG_FUNCTION void
debug_varpool (void)
{
dump_varpool (stderr);
&& !DECL_EXTERNAL (decl))
return true;
- /* When emulating tls, we actually see references to the control
- variable, rather than the user-level variable. */
- if (!targetm.have_tls
- && TREE_CODE (decl) == VAR_DECL
- && DECL_THREAD_LOCAL_P (decl))
- {
- tree control = emutls_decl (decl);
- if (decide_is_variable_needed (varpool_node (control), control))
- return true;
- }
-
/* When not reordering top level variables, we have to assume that
we are going to keep everything. */
if (flag_toplevel_reorder)
return true;
}
+/* Return if DECL is constant and its initial value is known (so we can do
+ constant folding using DECL_INITIAL (decl)). */
+
+bool
+const_value_known_p (tree decl)
+{
+ if (TREE_CODE (decl) != VAR_DECL
+ &&TREE_CODE (decl) != CONST_DECL)
+ return false;
+
+ if (TREE_CODE (decl) == CONST_DECL
+ || DECL_IN_CONSTANT_POOL (decl))
+ return true;
+
+ gcc_assert (TREE_CODE (decl) == VAR_DECL);
+
+ if (!TREE_READONLY (decl))
+ return false;
+
+ /* Gimplifier takes away constructors of local vars */
+ if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
+ return DECL_INITIAL (decl) != NULL;
+
+ gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl));
+
+ /* 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 (decl)
+ && (DECL_EXTERNAL (decl)
+ || decl_replaceable_p (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;
+}
+
/* Mark DECL as finalized. By finalizing the declaration, frontend instruct the
middle end to output the variable to asm file, if needed or externally
visible. */
{
struct varpool_node *node = varpool_node (decl);
+ gcc_assert (TREE_STATIC (decl));
+
/* The first declaration of a variable that comes through this function
decides whether it is global (in C, has external linkage)
or local (in C, has internal linkage). So do nothing more
/* If the variable can be overwritten, return OVERWRITABLE. Takes
care of at least two notable extensions - the COMDAT variables
used to share template instantiations in C++. */
- if (!(*targetm.binds_local_p) (node->decl) && !DECL_COMDAT (node->decl))
+ if (!decl_replaceable_p (node->decl))
return AVAIL_OVERWRITABLE;
return AVAIL_AVAILABLE;
}
/* Attempt to mark ALIAS as an alias to DECL. Return TRUE if successful.
Extra name aliases are output whenever DECL is output. */
-bool
+struct varpool_node *
varpool_extra_name_alias (tree alias, tree decl)
{
struct varpool_node key, *alias_node, *decl_node, **slot;
/* If the varpool_node has been already created, fail. */
if (*slot)
- return false;
+ return NULL;
- alias_node = GGC_CNEW (struct varpool_node);
+ alias_node = ggc_alloc_cleared_varpool_node ();
alias_node->decl = alias;
alias_node->alias = 1;
alias_node->extra_name = decl_node;
decl_node->extra_name->prev = alias_node;
decl_node->extra_name = alias_node;
*slot = alias_node;
- return true;
+ return alias_node;
+}
+
+/* Return true when NODE is known to be used from other (non-LTO) object file.
+ Known only when doing LTO via linker plugin. */
+
+bool
+varpool_used_from_object_file_p (struct varpool_node *node)
+{
+ struct varpool_node *alias;
+
+ if (!TREE_PUBLIC (node->decl))
+ return false;
+ if (resolution_used_from_other_file_p (node->resolution))
+ return true;
+ for (alias = node->extra_name; alias; alias = alias->next)
+ if (TREE_PUBLIC (alias->decl)
+ && resolution_used_from_other_file_p (alias->resolution))
+ return true;
+ return false;
}
#include "gt-varpool.h"