LCOV - code coverage report
Current view: top level - gcc - varpool.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 84.8 % 394 334
Test Date: 2026-10-17 16:30:31 Functions: 80.0 % 30 24
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Callgraph handling code.
       2              :    Copyright (C) 2003-2026 Free Software Foundation, Inc.
       3              :    Contributed by Jan Hubicka
       4              : 
       5              : This file is part of GCC.
       6              : 
       7              : GCC is free software; you can redistribute it and/or modify it under
       8              : the terms of the GNU General Public License as published by the Free
       9              : Software Foundation; either version 3, or (at your option) any later
      10              : version.
      11              : 
      12              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      13              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      15              : for more details.
      16              : 
      17              : You should have received a copy of the GNU General Public License
      18              : along with GCC; see the file COPYING3.  If not see
      19              : <http://www.gnu.org/licenses/>.  */
      20              : 
      21              : #include "config.h"
      22              : #include "system.h"
      23              : #include "coretypes.h"
      24              : #include "backend.h"
      25              : #include "target.h"
      26              : #include "tree.h"
      27              : #include "gimple.h"
      28              : #include "timevar.h"
      29              : #include "cgraph.h"
      30              : #include "lto-streamer.h"
      31              : #include "varasm.h"
      32              : #include "debug.h"
      33              : #include "output.h"
      34              : #include "omp-offload.h"
      35              : #include "context.h"
      36              : #include "stringpool.h"
      37              : #include "attribs.h"
      38              : #include "tree-pass.h"
      39              : 
      40              : const char * const tls_model_names[]={"none", "emulated",
      41              :                                       "global-dynamic", "local-dynamic",
      42              :                                       "initial-exec", "local-exec"};
      43              : 
      44              : /* List of hooks triggered on varpool_node events.  */
      45              : struct varpool_node_hook_list {
      46              :   varpool_node_hook hook;
      47              :   void *data;
      48              :   struct varpool_node_hook_list *next;
      49              : };
      50              : 
      51              : /* Register HOOK to be called with DATA on each removed node.  */
      52              : varpool_node_hook_list *
      53       309689 : symbol_table::add_varpool_removal_hook (varpool_node_hook hook, void *data)
      54              : {
      55       309689 :   varpool_node_hook_list *entry;
      56       619378 :   varpool_node_hook_list **ptr = &m_first_varpool_removal_hook;
      57              : 
      58       309689 :   entry = (varpool_node_hook_list *) xmalloc (sizeof (*entry));
      59       309689 :   entry->hook = hook;
      60       309689 :   entry->data = data;
      61       309689 :   entry->next = NULL;
      62       317960 :   while (*ptr)
      63         8271 :     ptr = &(*ptr)->next;
      64       309689 :   *ptr = entry;
      65       309689 :   return entry;
      66              : }
      67              : 
      68              : /* Remove ENTRY from the list of hooks called on removing nodes.  */
      69              : void
      70       295859 : symbol_table::remove_varpool_removal_hook (varpool_node_hook_list *entry)
      71              : {
      72       295859 :   varpool_node_hook_list **ptr = &m_first_varpool_removal_hook;
      73              : 
      74       303897 :   while (*ptr != entry)
      75         8038 :     ptr = &(*ptr)->next;
      76       295859 :   *ptr = entry->next;
      77       295859 :   free (entry);
      78       295859 : }
      79              : 
      80              : /* Call all node removal hooks.  */
      81              : void
      82     34659654 : symbol_table::call_varpool_removal_hooks (varpool_node *node)
      83              : {
      84     34659654 :   varpool_node_hook_list *entry = m_first_varpool_removal_hook;
      85     42236217 :   while (entry)
      86              :   {
      87      7576563 :     entry->hook (node, entry->data);
      88      7576563 :     entry = entry->next;
      89              :   }
      90     34659654 : }
      91              : 
      92              : /* Register HOOK to be called with DATA on each inserted node.  */
      93              : varpool_node_hook_list *
      94            0 : symbol_table::add_varpool_insertion_hook (varpool_node_hook hook, void *data)
      95              : {
      96            0 :   varpool_node_hook_list *entry;
      97            0 :   varpool_node_hook_list **ptr = &m_first_varpool_insertion_hook;
      98              : 
      99            0 :   entry = (varpool_node_hook_list *) xmalloc (sizeof (*entry));
     100            0 :   entry->hook = hook;
     101            0 :   entry->data = data;
     102            0 :   entry->next = NULL;
     103            0 :   while (*ptr)
     104            0 :     ptr = &(*ptr)->next;
     105            0 :   *ptr = entry;
     106            0 :   return entry;
     107              : }
     108              : 
     109              : /* Remove ENTRY from the list of hooks called on inserted nodes.  */
     110              : void
     111            0 : symbol_table::remove_varpool_insertion_hook (varpool_node_hook_list *entry)
     112              : {
     113            0 :   varpool_node_hook_list **ptr = &m_first_varpool_insertion_hook;
     114              : 
     115            0 :   while (*ptr != entry)
     116            0 :     ptr = &(*ptr)->next;
     117            0 :   *ptr = entry->next;
     118            0 :   free (entry);
     119            0 : }
     120              : 
     121              : /* Call all node insertion hooks.  */
     122              : void
     123         2419 : symbol_table::call_varpool_insertion_hooks (varpool_node *node)
     124              : {
     125         2419 :   varpool_node_hook_list *entry = m_first_varpool_insertion_hook;
     126         2419 :   while (entry)
     127              :   {
     128            0 :     entry->hook (node, entry->data);
     129            0 :     entry = entry->next;
     130              :   }
     131         2419 : }
     132              : 
     133              : /* Allocate new callgraph node and insert it into basic data structures.  */
     134              : 
     135              : varpool_node *
     136     38063763 : varpool_node::create_empty (void)
     137              : {
     138     38063763 :   return new (ggc_alloc<varpool_node> ()) varpool_node ();
     139              : }
     140              : 
     141              : /* Return varpool node assigned to DECL.  Create new one when needed.  */
     142              : varpool_node *
     143    273885001 : varpool_node::get_create (tree decl)
     144              : {
     145    273885001 :   varpool_node *node = varpool_node::get (decl);
     146    273885001 :   gcc_checking_assert (VAR_P (decl));
     147    273885001 :   if (node)
     148              :     return node;
     149              : 
     150     37992398 :   node = varpool_node::create_empty ();
     151     37992398 :   node->decl = decl;
     152              : 
     153     37992398 :   tree attr;
     154     37953937 :   if ((flag_openacc || flag_openmp)
     155     38191727 :       && (attr = lookup_attribute ("omp declare target",
     156       199329 :                                    DECL_ATTRIBUTES (decl))))
     157              :     {
     158         5121 :       node->offloadable = 1;
     159         5121 :       if (lookup_attribute ("omp groupprivate", DECL_ATTRIBUTES (decl)))
     160              :         {
     161           24 :           if (!value_member (get_identifier ("device_type(nohost)"),
     162           12 :                              TREE_VALUE (attr))
     163           22 :               && !lookup_attribute ("omp declare target nohost",
     164           10 :                                     DECL_ATTRIBUTES (decl)))
     165              :             /* FIXME: value_member is Fortran, nohost attribute is C/C++.  */
     166           10 :             sorry_at (DECL_SOURCE_LOCATION (decl),
     167              :                       "%qD with %<omp groupprivate%> on the host; "
     168              :                       "try %<device_type(nohost)%>", decl);
     169              :           else
     170            2 :             for (const char *c = getenv ("OFFLOAD_TARGET_NAMES"); c;)
     171              :               {
     172            0 :                 if (startswith (c, "nvptx"))  /* Supported.  */
     173              :                   {
     174            0 :                     if ((c = strchr (c, ':')))
     175            0 :                       c++;
     176              :                   }
     177              :                 else
     178              :                   {
     179            0 :                     sorry_at (DECL_SOURCE_LOCATION (decl),
     180              :                               "%qD with %<omp groupprivate%> on devices other "
     181              :                               "than nvptx; try %<-foffload=nvptx-none%>", decl);
     182            0 :                     break;
     183              :                   }
     184              :               }
     185              :         }
     186              :       if (ENABLE_OFFLOADING && !DECL_EXTERNAL (decl))
     187              :         {
     188              :           g->have_offload = true;
     189              :           if (!in_lto_p
     190              :               && !value_member (get_identifier ("local"),
     191              :                                 TREE_VALUE (attr)))
     192              :             vec_safe_push (offload_vars, decl);
     193              :         }
     194              :     }
     195              : 
     196     37992398 :   node->register_symbol ();
     197     37992398 :   return node;
     198              : }
     199              : 
     200              : /* Remove variable from symbol table.  */
     201              : 
     202              : void
     203     34659654 : varpool_node::remove (void)
     204              : {
     205     34659654 :   symtab->call_varpool_removal_hooks (this);
     206     34659654 :   lto_free_function_in_decl_state_for_node (this);
     207              : 
     208              :   /* When streaming we can have multiple nodes associated with decl.  */
     209     34659654 :   if (symtab->state == LTO_STREAMING)
     210              :     ;
     211              :   /* Keep constructor when it may be used for folding. We remove
     212              :      references to external variables before final compilation.  */
     213     66804977 :   else if (DECL_INITIAL (decl) && DECL_INITIAL (decl) != error_mark_node
     214     66803364 :            && !ctor_useable_for_folding_p ())
     215         5083 :     remove_initializer ();
     216              : 
     217     34659654 :   unregister (NULL);
     218     34659654 :   ggc_free (this);
     219     34659654 : }
     220              : 
     221              : /* Remove node initializer when it is no longer needed.  */
     222              : void
     223      2008430 : varpool_node::remove_initializer (void)
     224              : {
     225      2008430 :   if (DECL_INITIAL (decl)
     226         5628 :       && !DECL_IN_CONSTANT_POOL (decl)
     227              :       /* Keep vtables for BINFO folding.  */
     228         5628 :       && !DECL_VIRTUAL_P (decl)
     229              :       /* FIXME: http://gcc.gnu.org/PR55395 */
     230         5407 :       && debug_info_level == DINFO_LEVEL_NONE
     231              :       /* When doing declaration merging we have duplicate
     232              :          entries for given decl.  Do not attempt to remove
     233              :          the bodies, or we will end up removing
     234              :          wrong one.  */
     235      2011608 :       && symtab->state != LTO_STREAMING)
     236         3178 :     DECL_INITIAL (decl) = error_mark_node;
     237      2008430 : }
     238              : 
     239              : /* Dump given varpool node to F.  */
     240              : void
     241         2554 : varpool_node::dump (FILE *f)
     242              : {
     243         2554 :   dump_base (f);
     244         2554 :   fprintf (f, "  Availability: %s\n",
     245         2554 :            symtab->function_flags_ready
     246         2428 :            ? cgraph_availability_names[get_availability ()]
     247              :            : "not-ready");
     248         2554 :   fprintf (f, "  Varpool flags:");
     249         2554 :   if (DECL_INITIAL (decl))
     250         1522 :     fprintf (f, " initialized");
     251         2554 :   if (output)
     252            0 :     fprintf (f, " output");
     253         2554 :   if (used_by_single_function)
     254           43 :     fprintf (f, " used-by-single-function");
     255         2554 :   if (TREE_READONLY (decl))
     256         1442 :     fprintf (f, " read-only");
     257         2554 :   if (ctor_useable_for_folding_p ())
     258         1153 :     fprintf (f, " const-value-known");
     259         2554 :   if (writeonly)
     260            0 :     fprintf (f, " write-only");
     261         2554 :   if (tls_model)
     262           60 :     fprintf (f, " tls-%s", tls_model_names [tls_model]);
     263         2554 :   fprintf (f, "\n");
     264         2554 : }
     265              : 
     266              : 
     267              : /* Dump given varpool node to stderr.  */
     268            0 : void varpool_node::debug (void)
     269              : {
     270            0 :   varpool_node::dump (stderr);
     271            0 : }
     272              : 
     273              : /* Dump the variable pool to F.  */
     274              : void
     275            0 : varpool_node::dump_varpool (FILE *f)
     276              : {
     277            0 :   varpool_node *node;
     278              : 
     279            0 :   fprintf (f, "variable pool:\n\n");
     280            0 :   FOR_EACH_VARIABLE (node)
     281            0 :     node->dump (f);
     282            0 : }
     283              : 
     284              : /* Dump the variable pool to stderr.  */
     285              : 
     286              : DEBUG_FUNCTION void
     287            0 : varpool_node::debug_varpool (void)
     288              : {
     289            0 :   dump_varpool (stderr);
     290            0 : }
     291              : 
     292              : /* Given an assembler name, lookup node.  */
     293              : varpool_node *
     294            0 : varpool_node::get_for_asmname (tree asmname)
     295              : {
     296            0 :   if (symtab_node *node = symtab_node::get_for_asmname (asmname))
     297            0 :     return dyn_cast <varpool_node *> (node);
     298              :   else
     299              :     return NULL;
     300              : }
     301              : 
     302              : /* When doing LTO, read variable's constructor from disk if
     303              :    it is not already present.  */
     304              : 
     305              : tree
     306      7385040 : varpool_node::get_constructor (void)
     307              : {
     308      7385040 :   lto_file_decl_data *file_data;
     309      7385040 :   const char *data, *name;
     310      7385040 :   size_t len;
     311              : 
     312      7385040 :   if (DECL_INITIAL (decl) != error_mark_node
     313         7789 :       || !in_lto_p
     314      7392825 :       || !lto_file_data)
     315      7377255 :     return DECL_INITIAL (decl);
     316              : 
     317         7785 :   timevar_push (TV_IPA_LTO_CTORS_IN);
     318              : 
     319         7785 :   file_data = lto_file_data;
     320         7785 :   name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
     321              : 
     322              :   /* We may have renamed the declaration, e.g., a static function.  */
     323         7785 :   name = lto_get_decl_name_mapping (file_data, name);
     324         7785 :   struct lto_in_decl_state *decl_state
     325         7785 :          = lto_get_function_in_decl_state (file_data, decl);
     326              : 
     327        15570 :   data = lto_get_section_data (file_data, LTO_section_function_body,
     328         7785 :                                name, order - file_data->order_base,
     329              :                                &len, decl_state->compressed);
     330         7785 :   if (!data)
     331            0 :     fatal_error (input_location, "%s: section %s.%d is missing",
     332              :                  file_data->file_name,
     333            0 :                  name, order - file_data->order_base);
     334              : 
     335         7785 :   if (!quiet_flag)
     336            0 :     fprintf (stderr, " in:%s", IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
     337         7785 :   lto_input_variable_constructor (file_data, this, data);
     338         7785 :   gcc_assert (DECL_INITIAL (decl) != error_mark_node);
     339         7785 :   lto_stats.num_function_bodies++;
     340         7785 :   lto_free_section_data (file_data, LTO_section_function_body, name,
     341              :                          data, len, decl_state->compressed);
     342         7785 :   lto_free_function_in_decl_state_for_node (this);
     343         7785 :   timevar_pop (TV_IPA_LTO_CTORS_IN);
     344         7785 :   return DECL_INITIAL (decl);
     345              : }
     346              : 
     347              : /* Return true if variable has constructor that can be used for folding.  */
     348              : 
     349              : bool
     350     71258625 : varpool_node::ctor_useable_for_folding_p (void)
     351              : {
     352     71258625 :   varpool_node *real_node = this;
     353              : 
     354     71258625 :   if (real_node->alias && real_node->definition)
     355       254085 :     real_node = ultimate_alias_target ();
     356              : 
     357     71258625 :   if (TREE_CODE (decl) == CONST_DECL
     358     71258625 :       || DECL_IN_CONSTANT_POOL (decl))
     359              :     return true;
     360     71258144 :   if (TREE_THIS_VOLATILE (decl))
     361              :     return false;
     362              : 
     363              :   /* Avoid attempts to load constructors that was not streamed.  */
     364       868132 :   if (in_lto_p && DECL_INITIAL (real_node->decl) == error_mark_node
     365     71293239 :       && real_node->body_removed)
     366              :     return false;
     367              : 
     368              :   /* If we do not have a constructor, we can't use it.  */
     369     71220507 :   if (DECL_INITIAL (real_node->decl) == error_mark_node
     370     71220507 :       && !real_node->lto_file_data)
     371              :     return false;
     372              : 
     373              :   /* Folding may cross TU boundaries.  */
     374     71220346 :   if (must_remain_in_tu_body)
     375              :     return false;
     376              : 
     377              :   /* Vtables are defined by their types and must match no matter of interposition
     378              :      rules.  */
     379     71220346 :   if (DECL_VIRTUAL_P (decl))
     380              :     {
     381              :       /* The C++ front end creates VAR_DECLs for vtables of typeinfo
     382              :          classes not defined in the current TU so that it can refer
     383              :          to them from typeinfo objects.  Avoid returning NULL_TREE.  */
     384      1324773 :       return DECL_INITIAL (real_node->decl) != NULL;
     385              :     }
     386              : 
     387              :   /* An alias of a read-only variable is also read-only, since the variable
     388              :      is stored in read-only memory.  We also accept read-only aliases of
     389              :      non-read-only locations assuming that the user knows what he is asking
     390              :      for.  */
     391     69895573 :   if (!TREE_READONLY (decl) && !TREE_READONLY (real_node->decl))
     392              :     return false;
     393              : 
     394              :   /* Variables declared 'const' without an initializer
     395              :      have zero as the initializer if they may not be
     396              :      overridden at link or run time.
     397              : 
     398              :      It is actually requirement for C++ compiler to optimize const variables
     399              :      consistently. As a GNU extension, do not enforce this rule for user defined
     400              :      weak variables, so we support interposition on:
     401              :      static const int dummy = 0;
     402              :      extern const int foo __attribute__((__weak__, __alias__("dummy")));
     403              :    */
     404     33429668 :   if ((!DECL_INITIAL (real_node->decl)
     405     32386649 :        || (DECL_WEAK (decl) && !DECL_COMDAT (decl)))
     406     33430040 :       && ((DECL_EXTERNAL (decl) && !in_other_partition)
     407         6945 :           || decl_replaceable_p (decl, semantic_interposition)))
     408      1036932 :     return false;
     409              : 
     410              :   /* Variables declared `const' with an initializer are considered
     411              :      to not be overwritable with different initializer by default.
     412              : 
     413              :      ??? Previously we behaved so for scalar variables but not for array
     414              :      accesses.  */
     415              :   return true;
     416              : }
     417              : 
     418              : /* If DECLARATION is constant variable and its initial value is known
     419              :    (so we can do constant folding), return its constructor (DECL_INITIAL).
     420              :    This may be an expression or NULL when DECL is initialized to 0.
     421              :    Return ERROR_MARK_NODE otherwise.
     422              : 
     423              :    In LTO this may actually trigger reading the constructor from disk.
     424              :    For this reason varpool_ctor_useable_for_folding_p should be used when
     425              :    the actual constructor value is not needed.  */
     426              : 
     427              : tree
     428    148035334 : ctor_for_folding (tree decl)
     429              : {
     430    148035334 :   varpool_node *node, *real_node;
     431    148035334 :   tree real_decl;
     432              : 
     433    148035334 :   if (!VAR_P (decl) && TREE_CODE (decl) != CONST_DECL)
     434      4711816 :     return error_mark_node;
     435              : 
     436    143323518 :   if (TREE_CODE (decl) == CONST_DECL
     437    143323518 :       || DECL_IN_CONSTANT_POOL (decl))
     438        85592 :     return DECL_INITIAL (decl);
     439              : 
     440    143237926 :   if (TREE_THIS_VOLATILE (decl))
     441      2125284 :     return error_mark_node;
     442              : 
     443              :   /* Do not care about automatic variables.  Those are never initialized
     444              :      anyway, because gimplifier expands the code.  */
     445    141112642 :   if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
     446              :     {
     447    101181008 :       gcc_assert (!TREE_PUBLIC (decl));
     448              :       /* Unless this is called during FE folding.  */
     449    101181008 :       if (cfun
     450    101176344 :           && (cfun->curr_properties & (PROP_gimple | PROP_rtl)) == 0
     451      5848269 :           && TREE_READONLY (decl)
     452        21209 :           && !TREE_SIDE_EFFECTS (decl)
     453    101202217 :           && DECL_INITIAL (decl))
     454          431 :         return DECL_INITIAL (decl);
     455    101180577 :       return error_mark_node;
     456              :     }
     457              : 
     458     39931634 :   gcc_assert (VAR_P (decl));
     459              : 
     460     39931634 :   real_node = node = varpool_node::get (decl);
     461     39931634 :   if (node)
     462              :     {
     463     39385405 :       real_node = node->ultimate_alias_target ();
     464     39385405 :       real_decl = real_node->decl;
     465              :     }
     466              :   else
     467              :     real_decl = decl;
     468              : 
     469              :   /* See if we are dealing with alias.
     470              :      In most cases alias is just alternative symbol pointing to a given
     471              :      constructor.  This allows us to use interposition rules of DECL
     472              :      constructor of REAL_NODE.  However weakrefs are special by being just
     473              :      alternative name of their target (if defined).  */
     474     39931634 :   if (decl != real_decl)
     475              :     {
     476       253775 :       gcc_assert (!DECL_INITIAL (decl)
     477              :                   || (node->alias && node->get_alias_target () == real_node)
     478              :                   || DECL_INITIAL (decl) == error_mark_node);
     479       253775 :       while (node->transparent_alias && node->analyzed)
     480              :         {
     481            0 :           node = node->get_alias_target ();
     482            0 :           decl = node->decl;
     483              :         }
     484              :     }
     485              : 
     486     39931634 :   if ((!DECL_VIRTUAL_P (real_decl)
     487       657233 :        || DECL_INITIAL (real_decl) == error_mark_node
     488       656676 :        || !DECL_INITIAL (real_decl))
     489     40007128 :       && (!node || !node->ctor_useable_for_folding_p ()))
     490     37859399 :     return error_mark_node;
     491              : 
     492              :   /* OK, we can return constructor.  See if we need to fetch it from disk
     493              :      in LTO mode.  */
     494      2072235 :   if (DECL_INITIAL (real_decl) != error_mark_node
     495      2072235 :       || !in_lto_p)
     496      2070817 :     return DECL_INITIAL (real_decl);
     497         1418 :   return real_node->get_constructor ();
     498              : }
     499              : 
     500              : /* Add the variable DECL to the varpool.
     501              :    Unlike finalize_decl function is intended to be used
     502              :    by middle end and allows insertion of new variable at arbitrary point
     503              :    of compilation.  */
     504              : void
     505         2419 : varpool_node::add (tree decl)
     506              : {
     507         2419 :   varpool_node *node;
     508         2419 :   varpool_node::finalize_decl (decl);
     509         2419 :   node = varpool_node::get_create (decl);
     510         2419 :   symtab->call_varpool_insertion_hooks (node);
     511         2419 :   if (node->externally_visible_p ())
     512         2406 :     node->externally_visible = true;
     513         2419 :   if (lookup_attribute ("no_reorder", DECL_ATTRIBUTES (decl)))
     514            0 :     node->no_reorder = 1;
     515         2419 : }
     516              : 
     517              : /* Return variable availability.  See cgraph.h for description of individual
     518              :    return values.  */
     519              : enum availability
     520    174470831 : varpool_node::get_availability (symtab_node *ref)
     521              : {
     522    174470831 :   if (!definition && !in_other_partition)
     523              :     return AVAIL_NOT_AVAILABLE;
     524    151226959 :   if (!TREE_PUBLIC (decl))
     525              :     return AVAIL_AVAILABLE;
     526     55249630 :   if (DECL_IN_CONSTANT_POOL (decl)
     527     55249630 :       || DECL_VIRTUAL_P (decl))
     528              :     return AVAIL_AVAILABLE;
     529     55189369 :   if (transparent_alias && definition)
     530              :     {
     531            0 :       enum availability avail;
     532              : 
     533            0 :       ultimate_alias_target (&avail, ref);
     534            0 :       return avail;
     535              :     }
     536              :   /* If this is a reference from symbol itself and there are no aliases, we
     537              :      may be sure that the symbol was not interposed by something else because
     538              :      the symbol itself would be unreachable otherwise.  */
     539            0 :   if ((this == ref && !has_aliases_p ())
     540     55189369 :       || (ref && get_comdat_group ()
     541            0 :           && get_comdat_group () == ref->get_comdat_group ()))
     542              :     return AVAIL_AVAILABLE;
     543              :   /* If the variable can be overwritten, return OVERWRITABLE.  Takes
     544              :      care of at least one notable extension - the COMDAT variables
     545              :      used to share template instantiations in C++.  */
     546     55189369 :   if (decl_replaceable_p (decl, semantic_interposition)
     547     55189369 :       || (DECL_EXTERNAL (decl) && !in_other_partition))
     548     25505970 :     return AVAIL_INTERPOSABLE;
     549              :   return AVAIL_AVAILABLE;
     550              : }
     551              : 
     552              : void
     553      3099545 : varpool_node::analyze (void)
     554              : {
     555              :   /* When reading back varpool at LTO time, we re-construct the queue in order
     556              :      to have "needed" list right by inserting all needed nodes into varpool.
     557              :      We however don't want to re-analyze already analyzed nodes.  */
     558      3099545 :   if (!analyzed)
     559              :     {
     560      3099545 :       gcc_assert (!in_lto_p || symtab->function_flags_ready);
     561              :       /* Compute the alignment early so function body expanders are
     562              :          already informed about increased alignment.  */
     563      3099545 :       align_variable (decl, 0);
     564              :     }
     565      3099545 :   if (alias)
     566          135 :     resolve_alias (varpool_node::get (alias_target));
     567      3099410 :   else if (DECL_INITIAL (decl))
     568      2036785 :     record_references_in_initializer (decl, analyzed);
     569      3099545 :   analyzed = true;
     570      3099545 : }
     571              : 
     572              : /* Assemble thunks and aliases associated to varpool node.  */
     573              : 
     574              : void
     575      2860577 : varpool_node::assemble_aliases (void)
     576              : {
     577      2860577 :   ipa_ref *ref;
     578              : 
     579      2865904 :   FOR_EACH_ALIAS (this, ref)
     580              :     {
     581         5327 :       varpool_node *alias = dyn_cast <varpool_node *> (ref->referring);
     582         5327 :       if (alias->symver)
     583            0 :         do_assemble_symver (alias->decl,
     584              :                             DECL_ASSEMBLER_NAME (decl));
     585         5327 :       else if (!alias->transparent_alias)
     586         5327 :         do_assemble_alias (alias->decl,
     587              :                            DECL_ASSEMBLER_NAME (decl));
     588         5327 :       alias->assemble_aliases ();
     589              :     }
     590      2860577 : }
     591              : 
     592              : /* Output one variable, if necessary.  Return whether we output it.  */
     593              : 
     594              : bool
     595      2863194 : varpool_node::assemble_decl (void)
     596              : {
     597              :   /* Aliases are output when their target is produced or by
     598              :      output_weakrefs.  */
     599      2863194 :   if (alias)
     600              :     return false;
     601              : 
     602              :   /* Constant pool is output from RTL land when the reference
     603              :      survive till this level.  */
     604      2857864 :   if (DECL_IN_CONSTANT_POOL (decl) && TREE_ASM_WRITTEN (decl))
     605              :     return false;
     606              : 
     607              :   /* Decls with VALUE_EXPR should not be in the varpool at all.  They
     608              :      are not real variables, but just info for debugging and codegen.
     609              :      Unfortunately at the moment emutls is not updating varpool correctly
     610              :      after turning real vars into value_expr vars.  */
     611      2855432 :   if (DECL_HAS_VALUE_EXPR_P (decl)
     612      2855432 :       && !targetm.have_tls)
     613              :     return false;
     614              : 
     615              :   /* Hard register vars do not need to be output.  */
     616      2855432 :   if (DECL_HARD_REGISTER (decl))
     617              :     return false;
     618              : 
     619      2855432 :   gcc_checking_assert (!TREE_ASM_WRITTEN (decl)
     620              :                        && VAR_P (decl)
     621              :                        && !DECL_HAS_VALUE_EXPR_P (decl));
     622              : 
     623      2855432 :   if (!in_other_partition
     624      2855432 :       && !DECL_EXTERNAL (decl))
     625              :     {
     626      2855250 :       get_constructor ();
     627      2855250 :       assemble_variable (decl, 0, 1, 0);
     628      2855250 :       gcc_assert (TREE_ASM_WRITTEN (decl));
     629      2855250 :       gcc_assert (definition);
     630      2855250 :       assemble_aliases ();
     631              :       /* After the parser has generated debugging information, augment
     632              :          this information with any new location/etc information that may
     633              :          have become available after the compilation proper.  */
     634      2855250 :       debug_hooks->late_global_decl (decl);
     635      2855250 :       return true;
     636              :     }
     637              : 
     638              :   return false;
     639              : }
     640              : 
     641              : /* Add NODE to queue starting at FIRST.
     642              :    The queue is linked via AUX pointers and terminated by pointer to 1.  */
     643              : 
     644              : static void
     645      4765050 : enqueue_node (varpool_node *node, varpool_node **first)
     646              : {
     647      4765050 :   if (node->aux)
     648              :     return;
     649      2858227 :   gcc_checking_assert (*first);
     650      2858227 :   node->aux = *first;
     651      2858227 :   *first = node;
     652              : }
     653              : 
     654              : /* Optimization of function bodies might've rendered some variables as
     655              :    unnecessary so we want to avoid these from being compiled.  Re-do
     656              :    reachability starting from variables that are either externally visible
     657              :    or was referred from the asm output routines.  */
     658              : 
     659              : void
     660       237544 : symbol_table::remove_unreferenced_decls (void)
     661              : {
     662       237544 :   varpool_node *next, *node;
     663       237544 :   varpool_node *first = (varpool_node *)(void *)1;
     664       237544 :   int i;
     665       237544 :   ipa_ref *ref = NULL;
     666       237544 :   hash_set<varpool_node *> referenced;
     667              : 
     668       237544 :   if (seen_error ())
     669            0 :     return;
     670              : 
     671       237544 :   if (dump_file)
     672           72 :     fprintf (dump_file, "Trivially needed variables:");
     673      3154055 :   FOR_EACH_DEFINED_VARIABLE (node)
     674              :     {
     675      2916511 :       if (node->analyzed
     676      2916511 :           && (!node->can_remove_if_no_refs_p ()
     677              :               /* We just expanded all function bodies.  See if any of
     678              :                  them needed the variable.  */
     679      1413663 :               || DECL_RTL_SET_P (node->decl)))
     680              :         {
     681      2241530 :           enqueue_node (node, &first);
     682      2241530 :           if (dump_file)
     683           59 :             fprintf (dump_file, " %s", node->dump_asm_name ());
     684              :         }
     685              :     }
     686      3095771 :   while (first != (varpool_node *)(void *)1)
     687              :     {
     688      2858227 :       node = first;
     689      2858227 :       first = (varpool_node *)first->aux;
     690              : 
     691      2858227 :       if (node->same_comdat_group)
     692              :         {
     693              :           symtab_node *next;
     694       210996 :           for (next = node->same_comdat_group;
     695       220992 :                next != node;
     696       210996 :                next = next->same_comdat_group)
     697              :             {
     698       210996 :               varpool_node *vnext = dyn_cast <varpool_node *> (next);
     699       421992 :               if (vnext && vnext->analyzed && !next->comdat_local_p ())
     700       210990 :                 enqueue_node (vnext, &first);
     701              :             }
     702              :         }
     703      9445240 :       for (i = 0; node->iterate_reference (i, ref); i++)
     704              :         {
     705      3491242 :           varpool_node *vnode = dyn_cast <varpool_node *> (ref->referred);
     706      3491242 :           if (vnode
     707      2560030 :               && !vnode->in_other_partition
     708      2560023 :               && (!DECL_EXTERNAL (ref->referred->decl)
     709       247486 :                   || vnode->alias)
     710      5803779 :               && vnode->analyzed)
     711      2312530 :             enqueue_node (vnode, &first);
     712              :           else
     713              :             {
     714      1178712 :               if (vnode)
     715       247500 :                 referenced.add (vnode);
     716      1178712 :               while (vnode && vnode->alias && vnode->definition)
     717              :                 {
     718            0 :                   vnode = vnode->get_alias_target ();
     719            0 :                   gcc_checking_assert (vnode);
     720            0 :                   referenced.add (vnode);
     721              :                 }
     722              :             }
     723              :         }
     724              :     }
     725       237544 :   if (dump_file)
     726           72 :     fprintf (dump_file, "\nRemoving variables:");
     727      3154055 :   for (node = first_defined_variable (); node; node = next)
     728              :     {
     729      2916511 :       next = next_defined_variable (node);
     730      2916511 :       if (!node->aux && !node->no_reorder)
     731              :         {
     732        58283 :           if (dump_file)
     733            0 :             fprintf (dump_file, " %s", node->dump_asm_name ());
     734        58283 :           if (referenced.contains(node))
     735            0 :             node->remove_initializer ();
     736              :           else
     737        58283 :             node->remove ();
     738              :         }
     739              :     }
     740              : 
     741       237544 :   if (dump_file)
     742           72 :     fprintf (dump_file, "\n");
     743       237544 : }
     744              : 
     745              : /* For variables in named sections make sure get_variable_section
     746              :    is called before we switch to those sections.  Then section
     747              :    conflicts between read-only and read-only requiring relocations
     748              :    sections can be resolved.  */
     749              : void
     750      2850490 : varpool_node::finalize_named_section_flags (void)
     751              : {
     752      2850490 :   if (!TREE_ASM_WRITTEN (decl)
     753      2848297 :       && !alias
     754      2843000 :       && !in_other_partition
     755      2843000 :       && !DECL_EXTERNAL (decl)
     756      2842964 :       && VAR_P (decl)
     757      2842964 :       && !DECL_HAS_VALUE_EXPR_P (decl)
     758      5693454 :       && get_section ())
     759      1436613 :     get_variable_section (decl, false);
     760      2850490 : }
     761              : 
     762              : /* Output all variables enqueued to be assembled.  */
     763              : bool
     764       237831 : symbol_table::output_variables (void)
     765              : {
     766       237831 :   bool changed = false;
     767       237831 :   varpool_node *node;
     768              : 
     769       237831 :   if (seen_error ())
     770              :     return false;
     771              : 
     772       237544 :   remove_unreferenced_decls ();
     773              : 
     774       237544 :   timevar_push (TV_VAROUT);
     775              : 
     776      3095772 :   FOR_EACH_DEFINED_VARIABLE (node)
     777              :     {
     778              :       /* Handled in output_in_order.  */
     779      2858228 :       if (node->no_reorder)
     780      1008346 :         continue;
     781              : 
     782      1849882 :       node->finalize_named_section_flags ();
     783              :     }
     784              : 
     785              :   /* There is a similar loop in output_in_order.  Please keep them in sync.  */
     786      3392432 :   FOR_EACH_VARIABLE (node)
     787              :     {
     788              :       /* Handled in output_in_order.  */
     789      3154888 :       if (node->no_reorder)
     790      1009026 :         continue;
     791      2145862 :       if (DECL_HARD_REGISTER (node->decl)
     792      2145862 :           || DECL_HAS_VALUE_EXPR_P (node->decl))
     793           63 :         continue;
     794      2145799 :       if (node->definition)
     795      1849819 :         changed |= node->assemble_decl ();
     796              :       else
     797       295980 :         assemble_undefined_decl (node->decl);
     798              :     }
     799       237544 :   timevar_pop (TV_VAROUT);
     800       237544 :   return changed;
     801              : }
     802              : 
     803              : /* Attempt to mark ALIAS as an alias to DECL.  Return TRUE if successful.
     804              :    Extra name aliases are output whenever DECL is output.  */
     805              : 
     806              : varpool_node *
     807        13105 : varpool_node::create_alias (tree alias, tree decl)
     808              : {
     809        13105 :   varpool_node *alias_node;
     810              : 
     811        13105 :   gcc_assert (VAR_P (decl));
     812        13105 :   gcc_assert (VAR_P (alias));
     813        13105 :   alias_node = varpool_node::get_create (alias);
     814        13105 :   alias_node->alias = true;
     815        13105 :   alias_node->definition = true;
     816        13105 :   alias_node->semantic_interposition = flag_semantic_interposition;
     817        13105 :   alias_node->alias_target = decl;
     818        13105 :   if (lookup_attribute ("weakref", DECL_ATTRIBUTES (alias)) != NULL)
     819           11 :     alias_node->weakref = alias_node->transparent_alias = true;
     820        13105 :   return alias_node;
     821              : }
     822              : 
     823              : /* Attempt to mark ALIAS as an alias to DECL.  Return TRUE if successful.
     824              :    Extra name aliases are output whenever DECL is output.  */
     825              : 
     826              : varpool_node *
     827           74 : varpool_node::create_extra_name_alias (tree alias, tree decl)
     828              : {
     829           74 :   varpool_node *alias_node;
     830              : 
     831              :   /* If aliases aren't supported by the assembler, fail.  */
     832           74 :   if (!TARGET_SUPPORTS_ALIASES)
     833              :     return NULL;
     834              : 
     835           74 :   alias_node = varpool_node::create_alias (alias, decl);
     836           74 :   alias_node->cpp_implicit_alias = true;
     837              : 
     838              :   /* Extra name alias mechanism creates aliases really late
     839              :      via DECL_ASSEMBLER_NAME mechanism.
     840              :      This is unfortunate because they are not going through the
     841              :      standard channels.  Ensure they get output.  */
     842           74 :   if (symtab->cpp_implicit_aliases_done)
     843           74 :     alias_node->resolve_alias (varpool_node::get_create (decl));
     844           74 :   return alias_node;
     845              : }
     846              : 
     847              : /* Worker for call_for_symbol_and_aliases.  */
     848              : 
     849              : bool
     850         7240 : varpool_node::call_for_symbol_and_aliases_1 (bool (*callback) (varpool_node *,
     851              :                                                                void *),
     852              :                                              void *data,
     853              :                                              bool include_overwritable)
     854              : {
     855         7240 :   ipa_ref *ref;
     856              : 
     857        30509 :   FOR_EACH_ALIAS (this, ref)
     858              :     {
     859        23269 :       varpool_node *alias = dyn_cast <varpool_node *> (ref->referring);
     860        23269 :       if (include_overwritable
     861        23269 :           || alias->get_availability () > AVAIL_INTERPOSABLE)
     862        23269 :         if (alias->call_for_symbol_and_aliases (callback, data,
     863              :                                                 include_overwritable))
     864              :           return true;
     865              :     }
     866              :   return false;
     867              : }
        

Generated by: LCOV version 2.5.0-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.