xref: /dflybsd-src/contrib/gcc-8.0/gcc/varpool.c (revision 95059079af47f9a66a175f374f2da1a5020e3255)
138fd1498Szrj /* Callgraph handling code.
238fd1498Szrj    Copyright (C) 2003-2018 Free Software Foundation, Inc.
338fd1498Szrj    Contributed by Jan Hubicka
438fd1498Szrj 
538fd1498Szrj This file is part of GCC.
638fd1498Szrj 
738fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
838fd1498Szrj the terms of the GNU General Public License as published by the Free
938fd1498Szrj Software Foundation; either version 3, or (at your option) any later
1038fd1498Szrj version.
1138fd1498Szrj 
1238fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1338fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
1438fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1538fd1498Szrj for more details.
1638fd1498Szrj 
1738fd1498Szrj You should have received a copy of the GNU General Public License
1838fd1498Szrj along with GCC; see the file COPYING3.  If not see
1938fd1498Szrj <http://www.gnu.org/licenses/>.  */
2038fd1498Szrj 
2138fd1498Szrj #include "config.h"
2238fd1498Szrj #include "system.h"
2338fd1498Szrj #include "coretypes.h"
2438fd1498Szrj #include "backend.h"
2538fd1498Szrj #include "target.h"
2638fd1498Szrj #include "tree.h"
2738fd1498Szrj #include "gimple.h"
2838fd1498Szrj #include "timevar.h"
2938fd1498Szrj #include "cgraph.h"
3038fd1498Szrj #include "lto-streamer.h"
3138fd1498Szrj #include "varasm.h"
3238fd1498Szrj #include "debug.h"
3338fd1498Szrj #include "output.h"
3438fd1498Szrj #include "omp-offload.h"
3538fd1498Szrj #include "context.h"
3638fd1498Szrj #include "stringpool.h"
3738fd1498Szrj #include "attribs.h"
3838fd1498Szrj 
3938fd1498Szrj const char * const tls_model_names[]={"none", "emulated",
4038fd1498Szrj 				      "global-dynamic", "local-dynamic",
4138fd1498Szrj 				      "initial-exec", "local-exec"};
4238fd1498Szrj 
4338fd1498Szrj /* List of hooks triggered on varpool_node events.  */
4438fd1498Szrj struct varpool_node_hook_list {
4538fd1498Szrj   varpool_node_hook hook;
4638fd1498Szrj   void *data;
4738fd1498Szrj   struct varpool_node_hook_list *next;
4838fd1498Szrj };
4938fd1498Szrj 
5038fd1498Szrj /* Register HOOK to be called with DATA on each removed node.  */
5138fd1498Szrj varpool_node_hook_list *
add_varpool_removal_hook(varpool_node_hook hook,void * data)5238fd1498Szrj symbol_table::add_varpool_removal_hook (varpool_node_hook hook, void *data)
5338fd1498Szrj {
5438fd1498Szrj   varpool_node_hook_list *entry;
5538fd1498Szrj   varpool_node_hook_list **ptr = &m_first_varpool_removal_hook;
5638fd1498Szrj 
5738fd1498Szrj   entry = (varpool_node_hook_list *) xmalloc (sizeof (*entry));
5838fd1498Szrj   entry->hook = hook;
5938fd1498Szrj   entry->data = data;
6038fd1498Szrj   entry->next = NULL;
6138fd1498Szrj   while (*ptr)
6238fd1498Szrj     ptr = &(*ptr)->next;
6338fd1498Szrj   *ptr = entry;
6438fd1498Szrj   return entry;
6538fd1498Szrj }
6638fd1498Szrj 
6738fd1498Szrj /* Remove ENTRY from the list of hooks called on removing nodes.  */
6838fd1498Szrj void
remove_varpool_removal_hook(varpool_node_hook_list * entry)6938fd1498Szrj symbol_table::remove_varpool_removal_hook (varpool_node_hook_list *entry)
7038fd1498Szrj {
7138fd1498Szrj   varpool_node_hook_list **ptr = &m_first_varpool_removal_hook;
7238fd1498Szrj 
7338fd1498Szrj   while (*ptr != entry)
7438fd1498Szrj     ptr = &(*ptr)->next;
7538fd1498Szrj   *ptr = entry->next;
7638fd1498Szrj   free (entry);
7738fd1498Szrj }
7838fd1498Szrj 
7938fd1498Szrj /* Call all node removal hooks.  */
8038fd1498Szrj void
call_varpool_removal_hooks(varpool_node * node)8138fd1498Szrj symbol_table::call_varpool_removal_hooks (varpool_node *node)
8238fd1498Szrj {
8338fd1498Szrj   varpool_node_hook_list *entry = m_first_varpool_removal_hook;
8438fd1498Szrj   while (entry)
8538fd1498Szrj   {
8638fd1498Szrj     entry->hook (node, entry->data);
8738fd1498Szrj     entry = entry->next;
8838fd1498Szrj   }
8938fd1498Szrj }
9038fd1498Szrj 
9138fd1498Szrj /* Register HOOK to be called with DATA on each inserted node.  */
9238fd1498Szrj varpool_node_hook_list *
add_varpool_insertion_hook(varpool_node_hook hook,void * data)9338fd1498Szrj symbol_table::add_varpool_insertion_hook (varpool_node_hook hook, void *data)
9438fd1498Szrj {
9538fd1498Szrj   varpool_node_hook_list *entry;
9638fd1498Szrj   varpool_node_hook_list **ptr = &m_first_varpool_insertion_hook;
9738fd1498Szrj 
9838fd1498Szrj   entry = (varpool_node_hook_list *) xmalloc (sizeof (*entry));
9938fd1498Szrj   entry->hook = hook;
10038fd1498Szrj   entry->data = data;
10138fd1498Szrj   entry->next = NULL;
10238fd1498Szrj   while (*ptr)
10338fd1498Szrj     ptr = &(*ptr)->next;
10438fd1498Szrj   *ptr = entry;
10538fd1498Szrj   return entry;
10638fd1498Szrj }
10738fd1498Szrj 
10838fd1498Szrj /* Remove ENTRY from the list of hooks called on inserted nodes.  */
10938fd1498Szrj void
remove_varpool_insertion_hook(varpool_node_hook_list * entry)11038fd1498Szrj symbol_table::remove_varpool_insertion_hook (varpool_node_hook_list *entry)
11138fd1498Szrj {
11238fd1498Szrj   varpool_node_hook_list **ptr = &m_first_varpool_insertion_hook;
11338fd1498Szrj 
11438fd1498Szrj   while (*ptr != entry)
11538fd1498Szrj     ptr = &(*ptr)->next;
11638fd1498Szrj   *ptr = entry->next;
11738fd1498Szrj   free (entry);
11838fd1498Szrj }
11938fd1498Szrj 
12038fd1498Szrj /* Call all node insertion hooks.  */
12138fd1498Szrj void
call_varpool_insertion_hooks(varpool_node * node)12238fd1498Szrj symbol_table::call_varpool_insertion_hooks (varpool_node *node)
12338fd1498Szrj {
12438fd1498Szrj   varpool_node_hook_list *entry = m_first_varpool_insertion_hook;
12538fd1498Szrj   while (entry)
12638fd1498Szrj   {
12738fd1498Szrj     entry->hook (node, entry->data);
12838fd1498Szrj     entry = entry->next;
12938fd1498Szrj   }
13038fd1498Szrj }
13138fd1498Szrj 
13238fd1498Szrj /* Allocate new callgraph node and insert it into basic data structures.  */
13338fd1498Szrj 
13438fd1498Szrj varpool_node *
create_empty(void)13538fd1498Szrj varpool_node::create_empty (void)
13638fd1498Szrj {
13738fd1498Szrj   varpool_node *node = ggc_cleared_alloc<varpool_node> ();
13838fd1498Szrj   node->type = SYMTAB_VARIABLE;
13938fd1498Szrj   return node;
14038fd1498Szrj }
14138fd1498Szrj 
14238fd1498Szrj /* Return varpool node assigned to DECL.  Create new one when needed.  */
14338fd1498Szrj varpool_node *
get_create(tree decl)14438fd1498Szrj varpool_node::get_create (tree decl)
14538fd1498Szrj {
14638fd1498Szrj   varpool_node *node = varpool_node::get (decl);
14738fd1498Szrj   gcc_checking_assert (VAR_P (decl));
14838fd1498Szrj   if (node)
14938fd1498Szrj     return node;
15038fd1498Szrj 
15138fd1498Szrj   node = varpool_node::create_empty ();
15238fd1498Szrj   node->decl = decl;
15338fd1498Szrj 
15438fd1498Szrj   if ((flag_openacc || flag_openmp)
15538fd1498Szrj       && lookup_attribute ("omp declare target", DECL_ATTRIBUTES (decl)))
15638fd1498Szrj     {
15738fd1498Szrj       node->offloadable = 1;
15838fd1498Szrj       if (ENABLE_OFFLOADING && !DECL_EXTERNAL (decl))
15938fd1498Szrj 	{
16038fd1498Szrj 	  g->have_offload = true;
16138fd1498Szrj 	  if (!in_lto_p)
16238fd1498Szrj 	    vec_safe_push (offload_vars, decl);
16338fd1498Szrj 	}
16438fd1498Szrj     }
16538fd1498Szrj 
16638fd1498Szrj   node->register_symbol ();
16738fd1498Szrj   return node;
16838fd1498Szrj }
16938fd1498Szrj 
17038fd1498Szrj /* Remove variable from symbol table.  */
17138fd1498Szrj 
17238fd1498Szrj void
remove(void)17338fd1498Szrj varpool_node::remove (void)
17438fd1498Szrj {
17538fd1498Szrj   symtab->call_varpool_removal_hooks (this);
17638fd1498Szrj   if (lto_file_data)
17738fd1498Szrj     {
17838fd1498Szrj       lto_free_function_in_decl_state_for_node (this);
17938fd1498Szrj       lto_file_data = NULL;
18038fd1498Szrj     }
18138fd1498Szrj 
18238fd1498Szrj   /* When streaming we can have multiple nodes associated with decl.  */
18338fd1498Szrj   if (symtab->state == LTO_STREAMING)
18438fd1498Szrj     ;
18538fd1498Szrj   /* Keep constructor when it may be used for folding. We remove
18638fd1498Szrj      references to external variables before final compilation.  */
18738fd1498Szrj   else if (DECL_INITIAL (decl) && DECL_INITIAL (decl) != error_mark_node
18838fd1498Szrj 	   && !ctor_useable_for_folding_p ())
18938fd1498Szrj     remove_initializer ();
19038fd1498Szrj 
19138fd1498Szrj   unregister ();
19238fd1498Szrj   ggc_free (this);
19338fd1498Szrj }
19438fd1498Szrj 
19538fd1498Szrj /* Remove node initializer when it is no longer needed.  */
19638fd1498Szrj void
remove_initializer(void)19738fd1498Szrj varpool_node::remove_initializer (void)
19838fd1498Szrj {
19938fd1498Szrj   if (DECL_INITIAL (decl)
20038fd1498Szrj       && !DECL_IN_CONSTANT_POOL (decl)
20138fd1498Szrj       /* Keep vtables for BINFO folding.  */
20238fd1498Szrj       && !DECL_VIRTUAL_P (decl)
20338fd1498Szrj       /* FIXME: http://gcc.gnu.org/PR55395 */
20438fd1498Szrj       && debug_info_level == DINFO_LEVEL_NONE
20538fd1498Szrj       /* When doing declaration merging we have duplicate
20638fd1498Szrj 	 entries for given decl.  Do not attempt to remove
20738fd1498Szrj 	 the boides, or we will end up remiving
20838fd1498Szrj 	 wrong one.  */
20938fd1498Szrj       && symtab->state != LTO_STREAMING)
21038fd1498Szrj     DECL_INITIAL (decl) = error_mark_node;
21138fd1498Szrj }
21238fd1498Szrj 
21338fd1498Szrj /* Dump given varpool node to F.  */
21438fd1498Szrj void
dump(FILE * f)21538fd1498Szrj varpool_node::dump (FILE *f)
21638fd1498Szrj {
21738fd1498Szrj   dump_base (f);
21838fd1498Szrj   fprintf (f, "  Availability: %s\n",
21938fd1498Szrj 	   symtab->function_flags_ready
22038fd1498Szrj 	   ? cgraph_availability_names[get_availability ()]
22138fd1498Szrj 	   : "not-ready");
22238fd1498Szrj   fprintf (f, "  Varpool flags:");
22338fd1498Szrj   if (DECL_INITIAL (decl))
22438fd1498Szrj     fprintf (f, " initialized");
22538fd1498Szrj   if (output)
22638fd1498Szrj     fprintf (f, " output");
22738fd1498Szrj   if (used_by_single_function)
22838fd1498Szrj     fprintf (f, " used-by-single-function");
22938fd1498Szrj   if (need_bounds_init)
23038fd1498Szrj     fprintf (f, " need-bounds-init");
23138fd1498Szrj   if (TREE_READONLY (decl))
23238fd1498Szrj     fprintf (f, " read-only");
23338fd1498Szrj   if (ctor_useable_for_folding_p ())
23438fd1498Szrj     fprintf (f, " const-value-known");
23538fd1498Szrj   if (writeonly)
23638fd1498Szrj     fprintf (f, " write-only");
23738fd1498Szrj   if (tls_model)
23838fd1498Szrj     fprintf (f, " tls-%s", tls_model_names [tls_model]);
23938fd1498Szrj   fprintf (f, "\n");
24038fd1498Szrj }
24138fd1498Szrj 
24238fd1498Szrj 
24338fd1498Szrj /* Dump given varpool node to stderr.  */
debug(void)24438fd1498Szrj void varpool_node::debug (void)
24538fd1498Szrj {
24638fd1498Szrj   varpool_node::dump (stderr);
24738fd1498Szrj }
24838fd1498Szrj 
24938fd1498Szrj /* Dump the variable pool to F.  */
25038fd1498Szrj void
dump_varpool(FILE * f)25138fd1498Szrj varpool_node::dump_varpool (FILE *f)
25238fd1498Szrj {
25338fd1498Szrj   varpool_node *node;
25438fd1498Szrj 
25538fd1498Szrj   fprintf (f, "variable pool:\n\n");
25638fd1498Szrj   FOR_EACH_VARIABLE (node)
25738fd1498Szrj     node->dump (f);
25838fd1498Szrj }
25938fd1498Szrj 
26038fd1498Szrj /* Dump the variable pool to stderr.  */
26138fd1498Szrj 
26238fd1498Szrj DEBUG_FUNCTION void
debug_varpool(void)26338fd1498Szrj varpool_node::debug_varpool (void)
26438fd1498Szrj {
26538fd1498Szrj   dump_varpool (stderr);
26638fd1498Szrj }
26738fd1498Szrj 
26838fd1498Szrj /* Given an assembler name, lookup node.  */
26938fd1498Szrj varpool_node *
get_for_asmname(tree asmname)27038fd1498Szrj varpool_node::get_for_asmname (tree asmname)
27138fd1498Szrj {
27238fd1498Szrj   if (symtab_node *node = symtab_node::get_for_asmname (asmname))
27338fd1498Szrj     return dyn_cast <varpool_node *> (node);
27438fd1498Szrj   else
27538fd1498Szrj     return NULL;
27638fd1498Szrj }
27738fd1498Szrj 
27838fd1498Szrj /* When doing LTO, read variable's constructor from disk if
27938fd1498Szrj    it is not already present.  */
28038fd1498Szrj 
28138fd1498Szrj tree
get_constructor(void)28238fd1498Szrj varpool_node::get_constructor (void)
28338fd1498Szrj {
28438fd1498Szrj   lto_file_decl_data *file_data;
28538fd1498Szrj   const char *data, *name;
28638fd1498Szrj   size_t len;
28738fd1498Szrj 
28838fd1498Szrj   if (DECL_INITIAL (decl) != error_mark_node
28938fd1498Szrj       || !in_lto_p
29038fd1498Szrj       || !lto_file_data)
29138fd1498Szrj     return DECL_INITIAL (decl);
29238fd1498Szrj 
29338fd1498Szrj   timevar_push (TV_IPA_LTO_CTORS_IN);
29438fd1498Szrj 
29538fd1498Szrj   file_data = lto_file_data;
29638fd1498Szrj   name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
29738fd1498Szrj 
29838fd1498Szrj   /* We may have renamed the declaration, e.g., a static function.  */
29938fd1498Szrj   name = lto_get_decl_name_mapping (file_data, name);
30038fd1498Szrj   struct lto_in_decl_state *decl_state
30138fd1498Szrj 	 = lto_get_function_in_decl_state (file_data, decl);
30238fd1498Szrj 
30338fd1498Szrj   data = lto_get_section_data (file_data, LTO_section_function_body,
30438fd1498Szrj 			       name, &len, decl_state->compressed);
30538fd1498Szrj   if (!data)
30638fd1498Szrj     fatal_error (input_location, "%s: section %s is missing",
30738fd1498Szrj 		 file_data->file_name,
30838fd1498Szrj 		 name);
30938fd1498Szrj 
31038fd1498Szrj   lto_input_variable_constructor (file_data, this, data);
31138fd1498Szrj   gcc_assert (DECL_INITIAL (decl) != error_mark_node);
31238fd1498Szrj   lto_stats.num_function_bodies++;
31338fd1498Szrj   lto_free_section_data (file_data, LTO_section_function_body, name,
31438fd1498Szrj 			 data, len, decl_state->compressed);
31538fd1498Szrj   lto_free_function_in_decl_state_for_node (this);
31638fd1498Szrj   timevar_pop (TV_IPA_LTO_CTORS_IN);
31738fd1498Szrj   return DECL_INITIAL (decl);
31838fd1498Szrj }
31938fd1498Szrj 
32038fd1498Szrj /* Return true if variable has constructor that can be used for folding.  */
32138fd1498Szrj 
32238fd1498Szrj bool
ctor_useable_for_folding_p(void)32338fd1498Szrj varpool_node::ctor_useable_for_folding_p (void)
32438fd1498Szrj {
32538fd1498Szrj   varpool_node *real_node = this;
32638fd1498Szrj 
32738fd1498Szrj   if (real_node->alias && real_node->definition)
32838fd1498Szrj     real_node = ultimate_alias_target ();
32938fd1498Szrj 
33038fd1498Szrj   if (TREE_CODE (decl) == CONST_DECL
33138fd1498Szrj       || DECL_IN_CONSTANT_POOL (decl))
33238fd1498Szrj     return true;
33338fd1498Szrj   if (TREE_THIS_VOLATILE (decl))
33438fd1498Szrj     return false;
33538fd1498Szrj 
336*58e805e6Szrj   /* Avoid attempts to load constructors that was not streamed.  */
337*58e805e6Szrj   if (in_lto_p && DECL_INITIAL (real_node->decl) == error_mark_node
338*58e805e6Szrj       && real_node->body_removed)
339*58e805e6Szrj     return false;
340*58e805e6Szrj 
34138fd1498Szrj   /* If we do not have a constructor, we can't use it.  */
34238fd1498Szrj   if (DECL_INITIAL (real_node->decl) == error_mark_node
34338fd1498Szrj       && !real_node->lto_file_data)
34438fd1498Szrj     return false;
34538fd1498Szrj 
34638fd1498Szrj   /* Vtables are defined by their types and must match no matter of interposition
34738fd1498Szrj      rules.  */
34838fd1498Szrj   if (DECL_VIRTUAL_P (decl))
34938fd1498Szrj     {
35038fd1498Szrj       /* The C++ front end creates VAR_DECLs for vtables of typeinfo
35138fd1498Szrj 	 classes not defined in the current TU so that it can refer
35238fd1498Szrj 	 to them from typeinfo objects.  Avoid returning NULL_TREE.  */
35338fd1498Szrj       return DECL_INITIAL (real_node->decl) != NULL;
35438fd1498Szrj     }
35538fd1498Szrj 
35638fd1498Szrj   /* Alias of readonly variable is also readonly, since the variable is stored
35738fd1498Szrj      in readonly memory.  We also accept readonly aliases of non-readonly
35838fd1498Szrj      locations assuming that user knows what he is asking for.  */
35938fd1498Szrj   if (!TREE_READONLY (decl) && !TREE_READONLY (real_node->decl))
36038fd1498Szrj     return false;
36138fd1498Szrj 
36238fd1498Szrj   /* Variables declared 'const' without an initializer
36338fd1498Szrj      have zero as the initializer if they may not be
36438fd1498Szrj      overridden at link or run time.
36538fd1498Szrj 
36638fd1498Szrj      It is actually requirement for C++ compiler to optimize const variables
36738fd1498Szrj      consistently. As a GNU extension, do not enfore this rule for user defined
36838fd1498Szrj      weak variables, so we support interposition on:
36938fd1498Szrj      static const int dummy = 0;
37038fd1498Szrj      extern const int foo __attribute__((__weak__, __alias__("dummy")));
37138fd1498Szrj    */
37238fd1498Szrj   if ((!DECL_INITIAL (real_node->decl)
37338fd1498Szrj        || (DECL_WEAK (decl) && !DECL_COMDAT (decl)))
37438fd1498Szrj       && (DECL_EXTERNAL (decl) || decl_replaceable_p (decl)))
37538fd1498Szrj     return false;
37638fd1498Szrj 
37738fd1498Szrj   /* Variables declared `const' with an initializer are considered
37838fd1498Szrj      to not be overwritable with different initializer by default.
37938fd1498Szrj 
38038fd1498Szrj      ??? Previously we behaved so for scalar variables but not for array
38138fd1498Szrj      accesses.  */
38238fd1498Szrj   return true;
38338fd1498Szrj }
38438fd1498Szrj 
38538fd1498Szrj /* If DECLARATION is constant variable and its initial value is known
38638fd1498Szrj    (so we can do constant folding), return its constructor (DECL_INITIAL).
38738fd1498Szrj    This may be an expression or NULL when DECL is initialized to 0.
38838fd1498Szrj    Return ERROR_MARK_NODE otherwise.
38938fd1498Szrj 
39038fd1498Szrj    In LTO this may actually trigger reading the constructor from disk.
39138fd1498Szrj    For this reason varpool_ctor_useable_for_folding_p should be used when
39238fd1498Szrj    the actual constructor value is not needed.  */
39338fd1498Szrj 
39438fd1498Szrj tree
ctor_for_folding(tree decl)39538fd1498Szrj ctor_for_folding (tree decl)
39638fd1498Szrj {
39738fd1498Szrj   varpool_node *node, *real_node;
39838fd1498Szrj   tree real_decl;
39938fd1498Szrj 
40038fd1498Szrj   if (!VAR_P (decl) && TREE_CODE (decl) != CONST_DECL)
40138fd1498Szrj     return error_mark_node;
40238fd1498Szrj 
40338fd1498Szrj   /* Static constant bounds are created to be
40438fd1498Szrj      used instead of constants and therefore
40538fd1498Szrj      do not let folding it.  */
40638fd1498Szrj   if (POINTER_BOUNDS_P (decl))
40738fd1498Szrj     return error_mark_node;
40838fd1498Szrj 
40938fd1498Szrj   if (TREE_CODE (decl) == CONST_DECL
41038fd1498Szrj       || DECL_IN_CONSTANT_POOL (decl))
41138fd1498Szrj     return DECL_INITIAL (decl);
41238fd1498Szrj 
41338fd1498Szrj   if (TREE_THIS_VOLATILE (decl))
41438fd1498Szrj     return error_mark_node;
41538fd1498Szrj 
41638fd1498Szrj   /* Do not care about automatic variables.  Those are never initialized
41738fd1498Szrj      anyway, because gimplifier exapnds the code.  */
41838fd1498Szrj   if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
41938fd1498Szrj     {
42038fd1498Szrj       gcc_assert (!TREE_PUBLIC (decl));
42138fd1498Szrj       return error_mark_node;
42238fd1498Szrj     }
42338fd1498Szrj 
42438fd1498Szrj   gcc_assert (VAR_P (decl));
42538fd1498Szrj 
42638fd1498Szrj   real_node = node = varpool_node::get (decl);
42738fd1498Szrj   if (node)
42838fd1498Szrj     {
42938fd1498Szrj       real_node = node->ultimate_alias_target ();
43038fd1498Szrj       real_decl = real_node->decl;
43138fd1498Szrj     }
43238fd1498Szrj   else
43338fd1498Szrj     real_decl = decl;
43438fd1498Szrj 
43538fd1498Szrj   /* See if we are dealing with alias.
43638fd1498Szrj      In most cases alias is just alternative symbol pointing to a given
43738fd1498Szrj      constructor.  This allows us to use interposition rules of DECL
43838fd1498Szrj      constructor of REAL_NODE.  However weakrefs are special by being just
43938fd1498Szrj      alternative name of their target (if defined).  */
44038fd1498Szrj   if (decl != real_decl)
44138fd1498Szrj     {
44238fd1498Szrj       gcc_assert (!DECL_INITIAL (decl)
44338fd1498Szrj 		  || (node->alias && node->get_alias_target () == real_node)
44438fd1498Szrj 		  || DECL_INITIAL (decl) == error_mark_node);
44538fd1498Szrj       while (node->transparent_alias && node->analyzed)
44638fd1498Szrj 	{
44738fd1498Szrj 	  node = node->get_alias_target ();
44838fd1498Szrj 	  decl = node->decl;
44938fd1498Szrj 	}
45038fd1498Szrj     }
45138fd1498Szrj 
45238fd1498Szrj   if ((!DECL_VIRTUAL_P (real_decl)
45338fd1498Szrj        || DECL_INITIAL (real_decl) == error_mark_node
45438fd1498Szrj        || !DECL_INITIAL (real_decl))
45538fd1498Szrj       && (!node || !node->ctor_useable_for_folding_p ()))
45638fd1498Szrj     return error_mark_node;
45738fd1498Szrj 
45838fd1498Szrj   /* OK, we can return constructor.  See if we need to fetch it from disk
45938fd1498Szrj      in LTO mode.  */
46038fd1498Szrj   if (DECL_INITIAL (real_decl) != error_mark_node
46138fd1498Szrj       || !in_lto_p)
46238fd1498Szrj     return DECL_INITIAL (real_decl);
46338fd1498Szrj   return real_node->get_constructor ();
46438fd1498Szrj }
46538fd1498Szrj 
46638fd1498Szrj /* Add the variable DECL to the varpool.
46738fd1498Szrj    Unlike finalize_decl function is intended to be used
46838fd1498Szrj    by middle end and allows insertion of new variable at arbitrary point
46938fd1498Szrj    of compilation.  */
47038fd1498Szrj void
add(tree decl)47138fd1498Szrj varpool_node::add (tree decl)
47238fd1498Szrj {
47338fd1498Szrj   varpool_node *node;
47438fd1498Szrj   varpool_node::finalize_decl (decl);
47538fd1498Szrj   node = varpool_node::get_create (decl);
47638fd1498Szrj   symtab->call_varpool_insertion_hooks (node);
47738fd1498Szrj   if (node->externally_visible_p ())
47838fd1498Szrj     node->externally_visible = true;
47938fd1498Szrj   if (lookup_attribute ("no_reorder", DECL_ATTRIBUTES (decl)))
48038fd1498Szrj     node->no_reorder = 1;
48138fd1498Szrj }
48238fd1498Szrj 
48338fd1498Szrj /* Return variable availability.  See cgraph.h for description of individual
48438fd1498Szrj    return values.  */
48538fd1498Szrj enum availability
get_availability(symtab_node * ref)48638fd1498Szrj varpool_node::get_availability (symtab_node *ref)
48738fd1498Szrj {
48838fd1498Szrj   if (!definition)
48938fd1498Szrj     return AVAIL_NOT_AVAILABLE;
49038fd1498Szrj   if (!TREE_PUBLIC (decl))
49138fd1498Szrj     return AVAIL_AVAILABLE;
49238fd1498Szrj   if (DECL_IN_CONSTANT_POOL (decl)
49338fd1498Szrj       || DECL_VIRTUAL_P (decl))
49438fd1498Szrj     return AVAIL_AVAILABLE;
49538fd1498Szrj   if (transparent_alias && definition)
49638fd1498Szrj     {
49738fd1498Szrj       enum availability avail;
49838fd1498Szrj 
49938fd1498Szrj       ultimate_alias_target (&avail, ref);
50038fd1498Szrj       return avail;
50138fd1498Szrj     }
50238fd1498Szrj   /* If this is a reference from symbol itself and there are no aliases, we
50338fd1498Szrj      may be sure that the symbol was not interposed by something else because
50438fd1498Szrj      the symbol itself would be unreachable otherwise.  */
50538fd1498Szrj   if ((this == ref && !has_aliases_p ())
50638fd1498Szrj       || (ref && get_comdat_group ()
50738fd1498Szrj           && get_comdat_group () == ref->get_comdat_group ()))
50838fd1498Szrj     return AVAIL_AVAILABLE;
50938fd1498Szrj   /* If the variable can be overwritten, return OVERWRITABLE.  Takes
51038fd1498Szrj      care of at least one notable extension - the COMDAT variables
51138fd1498Szrj      used to share template instantiations in C++.  */
51238fd1498Szrj   if (decl_replaceable_p (decl)
51338fd1498Szrj       || DECL_EXTERNAL (decl))
51438fd1498Szrj     return AVAIL_INTERPOSABLE;
51538fd1498Szrj   return AVAIL_AVAILABLE;
51638fd1498Szrj }
51738fd1498Szrj 
51838fd1498Szrj void
analyze(void)51938fd1498Szrj varpool_node::analyze (void)
52038fd1498Szrj {
52138fd1498Szrj   /* When reading back varpool at LTO time, we re-construct the queue in order
52238fd1498Szrj      to have "needed" list right by inserting all needed nodes into varpool.
52338fd1498Szrj      We however don't want to re-analyze already analyzed nodes.  */
52438fd1498Szrj   if (!analyzed)
52538fd1498Szrj     {
52638fd1498Szrj       gcc_assert (!in_lto_p || symtab->function_flags_ready);
52738fd1498Szrj       /* Compute the alignment early so function body expanders are
52838fd1498Szrj 	 already informed about increased alignment.  */
52938fd1498Szrj       align_variable (decl, 0);
53038fd1498Szrj     }
53138fd1498Szrj   if (alias)
53238fd1498Szrj     resolve_alias (varpool_node::get (alias_target));
53338fd1498Szrj   else if (DECL_INITIAL (decl))
53438fd1498Szrj     record_references_in_initializer (decl, analyzed);
53538fd1498Szrj   analyzed = true;
53638fd1498Szrj }
53738fd1498Szrj 
53838fd1498Szrj /* Assemble thunks and aliases associated to varpool node.  */
53938fd1498Szrj 
54038fd1498Szrj void
assemble_aliases(void)54138fd1498Szrj varpool_node::assemble_aliases (void)
54238fd1498Szrj {
54338fd1498Szrj   ipa_ref *ref;
54438fd1498Szrj 
54538fd1498Szrj   FOR_EACH_ALIAS (this, ref)
54638fd1498Szrj     {
54738fd1498Szrj       varpool_node *alias = dyn_cast <varpool_node *> (ref->referring);
54838fd1498Szrj       if (!alias->transparent_alias)
54938fd1498Szrj 	do_assemble_alias (alias->decl,
55038fd1498Szrj 			   DECL_ASSEMBLER_NAME (decl));
55138fd1498Szrj       alias->assemble_aliases ();
55238fd1498Szrj     }
55338fd1498Szrj }
55438fd1498Szrj 
55538fd1498Szrj /* Output one variable, if necessary.  Return whether we output it.  */
55638fd1498Szrj 
55738fd1498Szrj bool
assemble_decl(void)55838fd1498Szrj varpool_node::assemble_decl (void)
55938fd1498Szrj {
56038fd1498Szrj   /* Aliases are outout when their target is produced or by
56138fd1498Szrj      output_weakrefs.  */
56238fd1498Szrj   if (alias)
56338fd1498Szrj     return false;
56438fd1498Szrj 
56538fd1498Szrj   /* Constant pool is output from RTL land when the reference
56638fd1498Szrj      survive till this level.  */
56738fd1498Szrj   if (DECL_IN_CONSTANT_POOL (decl) && TREE_ASM_WRITTEN (decl))
56838fd1498Szrj     return false;
56938fd1498Szrj 
57038fd1498Szrj   /* Decls with VALUE_EXPR should not be in the varpool at all.  They
57138fd1498Szrj      are not real variables, but just info for debugging and codegen.
57238fd1498Szrj      Unfortunately at the moment emutls is not updating varpool correctly
57338fd1498Szrj      after turning real vars into value_expr vars.  */
57438fd1498Szrj   if (DECL_HAS_VALUE_EXPR_P (decl)
57538fd1498Szrj       && !targetm.have_tls)
57638fd1498Szrj     return false;
57738fd1498Szrj 
57838fd1498Szrj   /* Hard register vars do not need to be output.  */
57938fd1498Szrj   if (DECL_HARD_REGISTER (decl))
58038fd1498Szrj     return false;
58138fd1498Szrj 
58238fd1498Szrj   gcc_checking_assert (!TREE_ASM_WRITTEN (decl)
58338fd1498Szrj 		       && VAR_P (decl)
58438fd1498Szrj 		       && !DECL_HAS_VALUE_EXPR_P (decl));
58538fd1498Szrj 
58638fd1498Szrj   if (!in_other_partition
58738fd1498Szrj       && !DECL_EXTERNAL (decl))
58838fd1498Szrj     {
58938fd1498Szrj       get_constructor ();
59038fd1498Szrj       assemble_variable (decl, 0, 1, 0);
59138fd1498Szrj       gcc_assert (TREE_ASM_WRITTEN (decl));
59238fd1498Szrj       gcc_assert (definition);
59338fd1498Szrj       assemble_aliases ();
59438fd1498Szrj       /* After the parser has generated debugging information, augment
59538fd1498Szrj 	 this information with any new location/etc information that may
59638fd1498Szrj 	 have become available after the compilation proper.  */
59738fd1498Szrj       debug_hooks->late_global_decl (decl);
59838fd1498Szrj       return true;
59938fd1498Szrj     }
60038fd1498Szrj 
60138fd1498Szrj   return false;
60238fd1498Szrj }
60338fd1498Szrj 
60438fd1498Szrj /* Add NODE to queue starting at FIRST.
60538fd1498Szrj    The queue is linked via AUX pointers and terminated by pointer to 1.  */
60638fd1498Szrj 
60738fd1498Szrj static void
enqueue_node(varpool_node * node,varpool_node ** first)60838fd1498Szrj enqueue_node (varpool_node *node, varpool_node **first)
60938fd1498Szrj {
61038fd1498Szrj   if (node->aux)
61138fd1498Szrj     return;
61238fd1498Szrj   gcc_checking_assert (*first);
61338fd1498Szrj   node->aux = *first;
61438fd1498Szrj   *first = node;
61538fd1498Szrj }
61638fd1498Szrj 
61738fd1498Szrj /* Optimization of function bodies might've rendered some variables as
61838fd1498Szrj    unnecessary so we want to avoid these from being compiled.  Re-do
61938fd1498Szrj    reachability starting from variables that are either externally visible
62038fd1498Szrj    or was referred from the asm output routines.  */
62138fd1498Szrj 
62238fd1498Szrj void
remove_unreferenced_decls(void)62338fd1498Szrj symbol_table::remove_unreferenced_decls (void)
62438fd1498Szrj {
62538fd1498Szrj   varpool_node *next, *node;
62638fd1498Szrj   varpool_node *first = (varpool_node *)(void *)1;
62738fd1498Szrj   int i;
62838fd1498Szrj   ipa_ref *ref = NULL;
62938fd1498Szrj   hash_set<varpool_node *> referenced;
63038fd1498Szrj 
63138fd1498Szrj   if (seen_error ())
63238fd1498Szrj     return;
63338fd1498Szrj 
63438fd1498Szrj   if (dump_file)
63538fd1498Szrj     fprintf (dump_file, "Trivially needed variables:");
63638fd1498Szrj   FOR_EACH_DEFINED_VARIABLE (node)
63738fd1498Szrj     {
63838fd1498Szrj       if (node->analyzed
63938fd1498Szrj 	  && (!node->can_remove_if_no_refs_p ()
64038fd1498Szrj 	      /* We just expanded all function bodies.  See if any of
64138fd1498Szrj 		 them needed the variable.  */
64238fd1498Szrj 	      || DECL_RTL_SET_P (node->decl)))
64338fd1498Szrj 	{
64438fd1498Szrj 	  enqueue_node (node, &first);
64538fd1498Szrj 	  if (dump_file)
64638fd1498Szrj 	    fprintf (dump_file, " %s", node->asm_name ());
64738fd1498Szrj 	}
64838fd1498Szrj     }
64938fd1498Szrj   while (first != (varpool_node *)(void *)1)
65038fd1498Szrj     {
65138fd1498Szrj       node = first;
65238fd1498Szrj       first = (varpool_node *)first->aux;
65338fd1498Szrj 
65438fd1498Szrj       if (node->same_comdat_group)
65538fd1498Szrj 	{
65638fd1498Szrj 	  symtab_node *next;
65738fd1498Szrj 	  for (next = node->same_comdat_group;
65838fd1498Szrj 	       next != node;
65938fd1498Szrj 	       next = next->same_comdat_group)
66038fd1498Szrj 	    {
66138fd1498Szrj 	      varpool_node *vnext = dyn_cast <varpool_node *> (next);
66238fd1498Szrj 	      if (vnext && vnext->analyzed && !next->comdat_local_p ())
66338fd1498Szrj 		enqueue_node (vnext, &first);
66438fd1498Szrj 	    }
66538fd1498Szrj 	}
66638fd1498Szrj       for (i = 0; node->iterate_reference (i, ref); i++)
66738fd1498Szrj 	{
66838fd1498Szrj 	  varpool_node *vnode = dyn_cast <varpool_node *> (ref->referred);
66938fd1498Szrj 	  if (vnode
67038fd1498Szrj 	      && !vnode->in_other_partition
67138fd1498Szrj 	      && (!DECL_EXTERNAL (ref->referred->decl)
67238fd1498Szrj 		  || vnode->alias)
67338fd1498Szrj 	      && vnode->analyzed)
67438fd1498Szrj 	    enqueue_node (vnode, &first);
67538fd1498Szrj 	  else
67638fd1498Szrj 	    {
67738fd1498Szrj 	      referenced.add (vnode);
67838fd1498Szrj 	      while (vnode && vnode->alias && vnode->definition)
67938fd1498Szrj 		{
68038fd1498Szrj 		  vnode = vnode->get_alias_target ();
68138fd1498Szrj 	          referenced.add (vnode);
68238fd1498Szrj 		}
68338fd1498Szrj 	    }
68438fd1498Szrj 	}
68538fd1498Szrj     }
68638fd1498Szrj   if (dump_file)
68738fd1498Szrj     fprintf (dump_file, "\nRemoving variables:");
68838fd1498Szrj   for (node = first_defined_variable (); node; node = next)
68938fd1498Szrj     {
69038fd1498Szrj       next = next_defined_variable (node);
69138fd1498Szrj       if (!node->aux && !node->no_reorder)
69238fd1498Szrj 	{
69338fd1498Szrj 	  if (dump_file)
69438fd1498Szrj 	    fprintf (dump_file, " %s", node->asm_name ());
69538fd1498Szrj 	  if (referenced.contains(node))
69638fd1498Szrj 	    node->remove_initializer ();
69738fd1498Szrj 	  else
69838fd1498Szrj 	    node->remove ();
69938fd1498Szrj 	}
70038fd1498Szrj     }
70138fd1498Szrj 
70238fd1498Szrj   if (dump_file)
70338fd1498Szrj     fprintf (dump_file, "\n");
70438fd1498Szrj }
70538fd1498Szrj 
70638fd1498Szrj /* For variables in named sections make sure get_variable_section
70738fd1498Szrj    is called before we switch to those sections.  Then section
70838fd1498Szrj    conflicts between read-only and read-only requiring relocations
70938fd1498Szrj    sections can be resolved.  */
71038fd1498Szrj void
finalize_named_section_flags(void)71138fd1498Szrj varpool_node::finalize_named_section_flags (void)
71238fd1498Szrj {
71338fd1498Szrj   if (!TREE_ASM_WRITTEN (decl)
71438fd1498Szrj       && !alias
71538fd1498Szrj       && !in_other_partition
71638fd1498Szrj       && !DECL_EXTERNAL (decl)
71738fd1498Szrj       && VAR_P (decl)
71838fd1498Szrj       && !DECL_HAS_VALUE_EXPR_P (decl)
71938fd1498Szrj       && get_section ())
72038fd1498Szrj     get_variable_section (decl, false);
72138fd1498Szrj }
72238fd1498Szrj 
72338fd1498Szrj /* Output all variables enqueued to be assembled.  */
72438fd1498Szrj bool
output_variables(void)72538fd1498Szrj symbol_table::output_variables (void)
72638fd1498Szrj {
72738fd1498Szrj   bool changed = false;
72838fd1498Szrj   varpool_node *node;
72938fd1498Szrj 
73038fd1498Szrj   if (seen_error ())
73138fd1498Szrj     return false;
73238fd1498Szrj 
73338fd1498Szrj   remove_unreferenced_decls ();
73438fd1498Szrj 
73538fd1498Szrj   timevar_push (TV_VAROUT);
73638fd1498Szrj 
73738fd1498Szrj   FOR_EACH_DEFINED_VARIABLE (node)
73838fd1498Szrj     {
73938fd1498Szrj       /* Handled in output_in_order.  */
74038fd1498Szrj       if (node->no_reorder)
74138fd1498Szrj 	continue;
74238fd1498Szrj 
74338fd1498Szrj       node->finalize_named_section_flags ();
74438fd1498Szrj     }
74538fd1498Szrj 
74638fd1498Szrj   /* There is a similar loop in output_in_order.  Please keep them in sync.  */
74738fd1498Szrj   FOR_EACH_VARIABLE (node)
74838fd1498Szrj     {
74938fd1498Szrj       /* Handled in output_in_order.  */
75038fd1498Szrj       if (node->no_reorder)
75138fd1498Szrj 	continue;
75238fd1498Szrj       if (DECL_HARD_REGISTER (node->decl)
75338fd1498Szrj 	  || DECL_HAS_VALUE_EXPR_P (node->decl))
75438fd1498Szrj 	continue;
75538fd1498Szrj       if (node->definition)
75638fd1498Szrj 	changed |= node->assemble_decl ();
75738fd1498Szrj       else
75838fd1498Szrj 	assemble_undefined_decl (node->decl);
75938fd1498Szrj     }
76038fd1498Szrj   timevar_pop (TV_VAROUT);
76138fd1498Szrj   return changed;
76238fd1498Szrj }
76338fd1498Szrj 
76438fd1498Szrj /* Attempt to mark ALIAS as an alias to DECL.  Return TRUE if successful.
76538fd1498Szrj    Extra name aliases are output whenever DECL is output.  */
76638fd1498Szrj 
76738fd1498Szrj varpool_node *
create_alias(tree alias,tree decl)76838fd1498Szrj varpool_node::create_alias (tree alias, tree decl)
76938fd1498Szrj {
77038fd1498Szrj   varpool_node *alias_node;
77138fd1498Szrj 
77238fd1498Szrj   gcc_assert (VAR_P (decl));
77338fd1498Szrj   gcc_assert (VAR_P (alias));
77438fd1498Szrj   alias_node = varpool_node::get_create (alias);
77538fd1498Szrj   alias_node->alias = true;
77638fd1498Szrj   alias_node->definition = true;
77738fd1498Szrj   alias_node->alias_target = decl;
77838fd1498Szrj   if (lookup_attribute ("weakref", DECL_ATTRIBUTES (alias)) != NULL)
77938fd1498Szrj     alias_node->weakref = alias_node->transparent_alias = true;
78038fd1498Szrj   return alias_node;
78138fd1498Szrj }
78238fd1498Szrj 
78338fd1498Szrj /* Attempt to mark ALIAS as an alias to DECL.  Return TRUE if successful.
78438fd1498Szrj    Extra name aliases are output whenever DECL is output.  */
78538fd1498Szrj 
78638fd1498Szrj varpool_node *
create_extra_name_alias(tree alias,tree decl)78738fd1498Szrj varpool_node::create_extra_name_alias (tree alias, tree decl)
78838fd1498Szrj {
78938fd1498Szrj   varpool_node *alias_node;
79038fd1498Szrj 
79138fd1498Szrj   /* If aliases aren't supported by the assembler, fail.  */
79238fd1498Szrj   if (!TARGET_SUPPORTS_ALIASES)
79338fd1498Szrj     return NULL;
79438fd1498Szrj 
79538fd1498Szrj   alias_node = varpool_node::create_alias (alias, decl);
79638fd1498Szrj   alias_node->cpp_implicit_alias = true;
79738fd1498Szrj 
79838fd1498Szrj   /* Extra name alias mechanizm creates aliases really late
79938fd1498Szrj      via DECL_ASSEMBLER_NAME mechanizm.
80038fd1498Szrj      This is unfortunate because they are not going through the
80138fd1498Szrj      standard channels.  Ensure they get output.  */
80238fd1498Szrj   if (symtab->cpp_implicit_aliases_done)
80338fd1498Szrj     alias_node->resolve_alias (varpool_node::get_create (decl));
80438fd1498Szrj   return alias_node;
80538fd1498Szrj }
80638fd1498Szrj 
80738fd1498Szrj /* Worker for call_for_symbol_and_aliases.  */
80838fd1498Szrj 
80938fd1498Szrj bool
call_for_symbol_and_aliases_1(bool (* callback)(varpool_node *,void *),void * data,bool include_overwritable)81038fd1498Szrj varpool_node::call_for_symbol_and_aliases_1 (bool (*callback) (varpool_node *,
81138fd1498Szrj 							       void *),
81238fd1498Szrj 					     void *data,
81338fd1498Szrj 					     bool include_overwritable)
81438fd1498Szrj {
81538fd1498Szrj   ipa_ref *ref;
81638fd1498Szrj 
81738fd1498Szrj   FOR_EACH_ALIAS (this, ref)
81838fd1498Szrj     {
81938fd1498Szrj       varpool_node *alias = dyn_cast <varpool_node *> (ref->referring);
82038fd1498Szrj       if (include_overwritable
82138fd1498Szrj 	  || alias->get_availability () > AVAIL_INTERPOSABLE)
82238fd1498Szrj 	if (alias->call_for_symbol_and_aliases (callback, data,
82338fd1498Szrj 					        include_overwritable))
82438fd1498Szrj 	  return true;
82538fd1498Szrj     }
82638fd1498Szrj   return false;
82738fd1498Szrj }
828