LCOV - code coverage report
Current view: top level - gcc - varpool.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 85.6 % 382 327
Test Date: 2026-03-28 14:25:54 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       300187 : symbol_table::add_varpool_removal_hook (varpool_node_hook hook, void *data)
      54              : {
      55       300187 :   varpool_node_hook_list *entry;
      56       600374 :   varpool_node_hook_list **ptr = &m_first_varpool_removal_hook;
      57              : 
      58       300187 :   entry = (varpool_node_hook_list *) xmalloc (sizeof (*entry));
      59       300187 :   entry->hook = hook;
      60       300187 :   entry->data = data;
      61       300187 :   entry->next = NULL;
      62       307757 :   while (*ptr)
      63         7570 :     ptr = &(*ptr)->next;
      64       300187 :   *ptr = entry;
      65       300187 :   return entry;
      66              : }
      67              : 
      68              : /* Remove ENTRY from the list of hooks called on removing nodes.  */
      69              : void
      70       286969 : symbol_table::remove_varpool_removal_hook (varpool_node_hook_list *entry)
      71              : {
      72       286969 :   varpool_node_hook_list **ptr = &m_first_varpool_removal_hook;
      73              : 
      74       294324 :   while (*ptr != entry)
      75         7355 :     ptr = &(*ptr)->next;
      76       286969 :   *ptr = entry->next;
      77       286969 :   free (entry);
      78       286969 : }
      79              : 
      80              : /* Call all node removal hooks.  */
      81              : void
      82     36408941 : symbol_table::call_varpool_removal_hooks (varpool_node *node)
      83              : {
      84     36408941 :   varpool_node_hook_list *entry = m_first_varpool_removal_hook;
      85     44474067 :   while (entry)
      86              :   {
      87      8065126 :     entry->hook (node, entry->data);
      88      8065126 :     entry = entry->next;
      89              :   }
      90     36408941 : }
      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         2373 : symbol_table::call_varpool_insertion_hooks (varpool_node *node)
     124              : {
     125         2373 :   varpool_node_hook_list *entry = m_first_varpool_insertion_hook;
     126         2373 :   while (entry)
     127              :   {
     128            0 :     entry->hook (node, entry->data);
     129            0 :     entry = entry->next;
     130              :   }
     131         2373 : }
     132              : 
     133              : /* Allocate new callgraph node and insert it into basic data structures.  */
     134              : 
     135              : varpool_node *
     136     39772808 : varpool_node::create_empty (void)
     137              : {
     138     39772808 :   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    289169145 : varpool_node::get_create (tree decl)
     144              : {
     145    289169145 :   varpool_node *node = varpool_node::get (decl);
     146    289169145 :   gcc_checking_assert (VAR_P (decl));
     147    289169145 :   if (node)
     148              :     return node;
     149              : 
     150     39702411 :   node = varpool_node::create_empty ();
     151     39702411 :   node->decl = decl;
     152              : 
     153     39664029 :   if ((flag_openacc || flag_openmp)
     154     39861020 :       && lookup_attribute ("omp declare target", DECL_ATTRIBUTES (decl)))
     155              :     {
     156         5065 :       node->offloadable = 1;
     157         5065 :       if (ENABLE_OFFLOADING && !DECL_EXTERNAL (decl))
     158              :         {
     159              :           g->have_offload = true;
     160              :           if (!in_lto_p)
     161              :             vec_safe_push (offload_vars, decl);
     162              :         }
     163              :     }
     164              : 
     165     39702411 :   node->register_symbol ();
     166     39702411 :   return node;
     167              : }
     168              : 
     169              : /* Remove variable from symbol table.  */
     170              : 
     171              : void
     172     36408941 : varpool_node::remove (void)
     173              : {
     174     36408941 :   symtab->call_varpool_removal_hooks (this);
     175     36408941 :   lto_free_function_in_decl_state_for_node (this);
     176              : 
     177              :   /* When streaming we can have multiple nodes associated with decl.  */
     178     36408941 :   if (symtab->state == LTO_STREAMING)
     179              :     ;
     180              :   /* Keep constructor when it may be used for folding. We remove
     181              :      references to external variables before final compilation.  */
     182     70505689 :   else if (DECL_INITIAL (decl) && DECL_INITIAL (decl) != error_mark_node
     183     70504124 :            && !ctor_useable_for_folding_p ())
     184         4136 :     remove_initializer ();
     185              : 
     186     36408941 :   unregister (NULL);
     187     36408941 :   ggc_free (this);
     188     36408941 : }
     189              : 
     190              : /* Remove node initializer when it is no longer needed.  */
     191              : void
     192      1990699 : varpool_node::remove_initializer (void)
     193              : {
     194      1990699 :   if (DECL_INITIAL (decl)
     195         4673 :       && !DECL_IN_CONSTANT_POOL (decl)
     196              :       /* Keep vtables for BINFO folding.  */
     197         4673 :       && !DECL_VIRTUAL_P (decl)
     198              :       /* FIXME: http://gcc.gnu.org/PR55395 */
     199         4452 :       && debug_info_level == DINFO_LEVEL_NONE
     200              :       /* When doing declaration merging we have duplicate
     201              :          entries for given decl.  Do not attempt to remove
     202              :          the bodies, or we will end up removing
     203              :          wrong one.  */
     204      1993940 :       && symtab->state != LTO_STREAMING)
     205         3241 :     DECL_INITIAL (decl) = error_mark_node;
     206      1990699 : }
     207              : 
     208              : /* Dump given varpool node to F.  */
     209              : void
     210         2468 : varpool_node::dump (FILE *f)
     211              : {
     212         2468 :   dump_base (f);
     213         2468 :   fprintf (f, "  Availability: %s\n",
     214         2468 :            symtab->function_flags_ready
     215         2342 :            ? cgraph_availability_names[get_availability ()]
     216              :            : "not-ready");
     217         2468 :   fprintf (f, "  Varpool flags:");
     218         2468 :   if (DECL_INITIAL (decl))
     219         1516 :     fprintf (f, " initialized");
     220         2468 :   if (output)
     221            0 :     fprintf (f, " output");
     222         2468 :   if (used_by_single_function)
     223           43 :     fprintf (f, " used-by-single-function");
     224         2468 :   if (TREE_READONLY (decl))
     225         1442 :     fprintf (f, " read-only");
     226         2468 :   if (ctor_useable_for_folding_p ())
     227         1153 :     fprintf (f, " const-value-known");
     228         2468 :   if (writeonly)
     229            0 :     fprintf (f, " write-only");
     230         2468 :   if (tls_model)
     231           59 :     fprintf (f, " tls-%s", tls_model_names [tls_model]);
     232         2468 :   fprintf (f, "\n");
     233         2468 : }
     234              : 
     235              : 
     236              : /* Dump given varpool node to stderr.  */
     237            0 : void varpool_node::debug (void)
     238              : {
     239            0 :   varpool_node::dump (stderr);
     240            0 : }
     241              : 
     242              : /* Dump the variable pool to F.  */
     243              : void
     244            0 : varpool_node::dump_varpool (FILE *f)
     245              : {
     246            0 :   varpool_node *node;
     247              : 
     248            0 :   fprintf (f, "variable pool:\n\n");
     249            0 :   FOR_EACH_VARIABLE (node)
     250            0 :     node->dump (f);
     251            0 : }
     252              : 
     253              : /* Dump the variable pool to stderr.  */
     254              : 
     255              : DEBUG_FUNCTION void
     256            0 : varpool_node::debug_varpool (void)
     257              : {
     258            0 :   dump_varpool (stderr);
     259            0 : }
     260              : 
     261              : /* Given an assembler name, lookup node.  */
     262              : varpool_node *
     263            0 : varpool_node::get_for_asmname (tree asmname)
     264              : {
     265            0 :   if (symtab_node *node = symtab_node::get_for_asmname (asmname))
     266            0 :     return dyn_cast <varpool_node *> (node);
     267              :   else
     268              :     return NULL;
     269              : }
     270              : 
     271              : /* When doing LTO, read variable's constructor from disk if
     272              :    it is not already present.  */
     273              : 
     274              : tree
     275      7323711 : varpool_node::get_constructor (void)
     276              : {
     277      7323711 :   lto_file_decl_data *file_data;
     278      7323711 :   const char *data, *name;
     279      7323711 :   size_t len;
     280              : 
     281      7323711 :   if (DECL_INITIAL (decl) != error_mark_node
     282         7672 :       || !in_lto_p
     283      7331379 :       || !lto_file_data)
     284      7316043 :     return DECL_INITIAL (decl);
     285              : 
     286         7668 :   timevar_push (TV_IPA_LTO_CTORS_IN);
     287              : 
     288         7668 :   file_data = lto_file_data;
     289         7668 :   name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
     290              : 
     291              :   /* We may have renamed the declaration, e.g., a static function.  */
     292         7668 :   name = lto_get_decl_name_mapping (file_data, name);
     293         7668 :   struct lto_in_decl_state *decl_state
     294         7668 :          = lto_get_function_in_decl_state (file_data, decl);
     295              : 
     296        15336 :   data = lto_get_section_data (file_data, LTO_section_function_body,
     297         7668 :                                name, order - file_data->order_base,
     298         7668 :                                &len, decl_state->compressed);
     299         7668 :   if (!data)
     300            0 :     fatal_error (input_location, "%s: section %s.%d is missing",
     301              :                  file_data->file_name,
     302            0 :                  name, order - file_data->order_base);
     303              : 
     304         7668 :   if (!quiet_flag)
     305            0 :     fprintf (stderr, " in:%s", IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
     306         7668 :   lto_input_variable_constructor (file_data, this, data);
     307         7668 :   gcc_assert (DECL_INITIAL (decl) != error_mark_node);
     308         7668 :   lto_stats.num_function_bodies++;
     309         7668 :   lto_free_section_data (file_data, LTO_section_function_body, name,
     310         7668 :                          data, len, decl_state->compressed);
     311         7668 :   lto_free_function_in_decl_state_for_node (this);
     312         7668 :   timevar_pop (TV_IPA_LTO_CTORS_IN);
     313         7668 :   return DECL_INITIAL (decl);
     314              : }
     315              : 
     316              : /* Return true if variable has constructor that can be used for folding.  */
     317              : 
     318              : bool
     319     73157082 : varpool_node::ctor_useable_for_folding_p (void)
     320              : {
     321     73157082 :   varpool_node *real_node = this;
     322              : 
     323     73157082 :   if (real_node->alias && real_node->definition)
     324       247791 :     real_node = ultimate_alias_target ();
     325              : 
     326     73157082 :   if (TREE_CODE (decl) == CONST_DECL
     327     73157082 :       || DECL_IN_CONSTANT_POOL (decl))
     328              :     return true;
     329     73156550 :   if (TREE_THIS_VOLATILE (decl))
     330              :     return false;
     331              : 
     332              :   /* Avoid attempts to load constructors that was not streamed.  */
     333       858763 :   if (in_lto_p && DECL_INITIAL (real_node->decl) == error_mark_node
     334     73191193 :       && real_node->body_removed)
     335              :     return false;
     336              : 
     337              :   /* If we do not have a constructor, we can't use it.  */
     338     73118948 :   if (DECL_INITIAL (real_node->decl) == error_mark_node
     339     73118948 :       && !real_node->lto_file_data)
     340              :     return false;
     341              : 
     342              :   /* Folding may cross TU boundaries.  */
     343     73118789 :   if (must_remain_in_tu_body)
     344              :     return false;
     345              : 
     346              :   /* Vtables are defined by their types and must match no matter of interposition
     347              :      rules.  */
     348     73118789 :   if (DECL_VIRTUAL_P (decl))
     349              :     {
     350              :       /* The C++ front end creates VAR_DECLs for vtables of typeinfo
     351              :          classes not defined in the current TU so that it can refer
     352              :          to them from typeinfo objects.  Avoid returning NULL_TREE.  */
     353      1316892 :       return DECL_INITIAL (real_node->decl) != NULL;
     354              :     }
     355              : 
     356              :   /* An alias of a read-only variable is also read-only, since the variable
     357              :      is stored in read-only memory.  We also accept read-only aliases of
     358              :      non-read-only locations assuming that the user knows what he is asking
     359              :      for.  */
     360     71801897 :   if (!TREE_READONLY (decl) && !TREE_READONLY (real_node->decl))
     361              :     return false;
     362              : 
     363              :   /* Variables declared 'const' without an initializer
     364              :      have zero as the initializer if they may not be
     365              :      overridden at link or run time.
     366              : 
     367              :      It is actually requirement for C++ compiler to optimize const variables
     368              :      consistently. As a GNU extension, do not enforce this rule for user defined
     369              :      weak variables, so we support interposition on:
     370              :      static const int dummy = 0;
     371              :      extern const int foo __attribute__((__weak__, __alias__("dummy")));
     372              :    */
     373     35368121 :   if ((!DECL_INITIAL (real_node->decl)
     374     34330564 :        || (DECL_WEAK (decl) && !DECL_COMDAT (decl)))
     375     35368727 :       && ((DECL_EXTERNAL (decl) && !in_other_partition)
     376         7106 :           || decl_replaceable_p (decl, semantic_interposition)))
     377      1031777 :     return false;
     378              : 
     379              :   /* Variables declared `const' with an initializer are considered
     380              :      to not be overwritable with different initializer by default.
     381              : 
     382              :      ??? Previously we behaved so for scalar variables but not for array
     383              :      accesses.  */
     384              :   return true;
     385              : }
     386              : 
     387              : /* If DECLARATION is constant variable and its initial value is known
     388              :    (so we can do constant folding), return its constructor (DECL_INITIAL).
     389              :    This may be an expression or NULL when DECL is initialized to 0.
     390              :    Return ERROR_MARK_NODE otherwise.
     391              : 
     392              :    In LTO this may actually trigger reading the constructor from disk.
     393              :    For this reason varpool_ctor_useable_for_folding_p should be used when
     394              :    the actual constructor value is not needed.  */
     395              : 
     396              : tree
     397    145642575 : ctor_for_folding (tree decl)
     398              : {
     399    145642575 :   varpool_node *node, *real_node;
     400    145642575 :   tree real_decl;
     401              : 
     402    145642575 :   if (!VAR_P (decl) && TREE_CODE (decl) != CONST_DECL)
     403      4429691 :     return error_mark_node;
     404              : 
     405    141212884 :   if (TREE_CODE (decl) == CONST_DECL
     406    141212884 :       || DECL_IN_CONSTANT_POOL (decl))
     407        85923 :     return DECL_INITIAL (decl);
     408              : 
     409    141126961 :   if (TREE_THIS_VOLATILE (decl))
     410      2160421 :     return error_mark_node;
     411              : 
     412              :   /* Do not care about automatic variables.  Those are never initialized
     413              :      anyway, because gimplifier expands the code.  */
     414    138966540 :   if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
     415              :     {
     416     99084532 :       gcc_assert (!TREE_PUBLIC (decl));
     417              :       /* Unless this is called during FE folding.  */
     418     99084532 :       if (cfun
     419     99079868 :           && (cfun->curr_properties & (PROP_gimple | PROP_rtl)) == 0
     420      5844183 :           && TREE_READONLY (decl)
     421        16577 :           && !TREE_SIDE_EFFECTS (decl)
     422     99101109 :           && DECL_INITIAL (decl))
     423          423 :         return DECL_INITIAL (decl);
     424     99084109 :       return error_mark_node;
     425              :     }
     426              : 
     427     39882008 :   gcc_assert (VAR_P (decl));
     428              : 
     429     39882008 :   real_node = node = varpool_node::get (decl);
     430     39882008 :   if (node)
     431              :     {
     432     39325797 :       real_node = node->ultimate_alias_target ();
     433     39325797 :       real_decl = real_node->decl;
     434              :     }
     435              :   else
     436              :     real_decl = decl;
     437              : 
     438              :   /* See if we are dealing with alias.
     439              :      In most cases alias is just alternative symbol pointing to a given
     440              :      constructor.  This allows us to use interposition rules of DECL
     441              :      constructor of REAL_NODE.  However weakrefs are special by being just
     442              :      alternative name of their target (if defined).  */
     443     39882008 :   if (decl != real_decl)
     444              :     {
     445       247487 :       gcc_assert (!DECL_INITIAL (decl)
     446              :                   || (node->alias && node->get_alias_target () == real_node)
     447              :                   || DECL_INITIAL (decl) == error_mark_node);
     448       247487 :       while (node->transparent_alias && node->analyzed)
     449              :         {
     450            0 :           node = node->get_alias_target ();
     451            0 :           decl = node->decl;
     452              :         }
     453              :     }
     454              : 
     455     39882008 :   if ((!DECL_VIRTUAL_P (real_decl)
     456       662704 :        || DECL_INITIAL (real_decl) == error_mark_node
     457       662147 :        || !DECL_INITIAL (real_decl))
     458     39953383 :       && (!node || !node->ctor_useable_for_folding_p ()))
     459     37812466 :     return error_mark_node;
     460              : 
     461              :   /* OK, we can return constructor.  See if we need to fetch it from disk
     462              :      in LTO mode.  */
     463      2069542 :   if (DECL_INITIAL (real_decl) != error_mark_node
     464      2069542 :       || !in_lto_p)
     465      2068174 :     return DECL_INITIAL (real_decl);
     466         1368 :   return real_node->get_constructor ();
     467              : }
     468              : 
     469              : /* Add the variable DECL to the varpool.
     470              :    Unlike finalize_decl function is intended to be used
     471              :    by middle end and allows insertion of new variable at arbitrary point
     472              :    of compilation.  */
     473              : void
     474         2373 : varpool_node::add (tree decl)
     475              : {
     476         2373 :   varpool_node *node;
     477         2373 :   varpool_node::finalize_decl (decl);
     478         2373 :   node = varpool_node::get_create (decl);
     479         2373 :   symtab->call_varpool_insertion_hooks (node);
     480         2373 :   if (node->externally_visible_p ())
     481         2360 :     node->externally_visible = true;
     482         2373 :   if (lookup_attribute ("no_reorder", DECL_ATTRIBUTES (decl)))
     483            0 :     node->no_reorder = 1;
     484         2373 : }
     485              : 
     486              : /* Return variable availability.  See cgraph.h for description of individual
     487              :    return values.  */
     488              : enum availability
     489    170679158 : varpool_node::get_availability (symtab_node *ref)
     490              : {
     491    170679158 :   if (!definition && !in_other_partition)
     492              :     return AVAIL_NOT_AVAILABLE;
     493    147462969 :   if (!TREE_PUBLIC (decl))
     494              :     return AVAIL_AVAILABLE;
     495     51696531 :   if (DECL_IN_CONSTANT_POOL (decl)
     496     51696531 :       || DECL_VIRTUAL_P (decl))
     497              :     return AVAIL_AVAILABLE;
     498     51637891 :   if (transparent_alias && definition)
     499              :     {
     500            0 :       enum availability avail;
     501              : 
     502            0 :       ultimate_alias_target (&avail, ref);
     503            0 :       return avail;
     504              :     }
     505              :   /* If this is a reference from symbol itself and there are no aliases, we
     506              :      may be sure that the symbol was not interposed by something else because
     507              :      the symbol itself would be unreachable otherwise.  */
     508            0 :   if ((this == ref && !has_aliases_p ())
     509     51637891 :       || (ref && get_comdat_group ()
     510            0 :           && get_comdat_group () == ref->get_comdat_group ()))
     511              :     return AVAIL_AVAILABLE;
     512              :   /* If the variable can be overwritten, return OVERWRITABLE.  Takes
     513              :      care of at least one notable extension - the COMDAT variables
     514              :      used to share template instantiations in C++.  */
     515     51637891 :   if (decl_replaceable_p (decl, semantic_interposition)
     516     51637891 :       || (DECL_EXTERNAL (decl) && !in_other_partition))
     517              :     return AVAIL_INTERPOSABLE;
     518              :   return AVAIL_AVAILABLE;
     519              : }
     520              : 
     521              : void
     522      3063562 : varpool_node::analyze (void)
     523              : {
     524              :   /* When reading back varpool at LTO time, we re-construct the queue in order
     525              :      to have "needed" list right by inserting all needed nodes into varpool.
     526              :      We however don't want to re-analyze already analyzed nodes.  */
     527      3063562 :   if (!analyzed)
     528              :     {
     529      3063562 :       gcc_assert (!in_lto_p || symtab->function_flags_ready);
     530              :       /* Compute the alignment early so function body expanders are
     531              :          already informed about increased alignment.  */
     532      3063562 :       align_variable (decl, 0);
     533              :     }
     534      3063562 :   if (alias)
     535          135 :     resolve_alias (varpool_node::get (alias_target));
     536      3063427 :   else if (DECL_INITIAL (decl))
     537      2006472 :     record_references_in_initializer (decl, analyzed);
     538      3063562 :   analyzed = true;
     539      3063562 : }
     540              : 
     541              : /* Assemble thunks and aliases associated to varpool node.  */
     542              : 
     543              : void
     544      2833355 : varpool_node::assemble_aliases (void)
     545              : {
     546      2833355 :   ipa_ref *ref;
     547              : 
     548      2838325 :   FOR_EACH_ALIAS (this, ref)
     549              :     {
     550         4970 :       varpool_node *alias = dyn_cast <varpool_node *> (ref->referring);
     551         4970 :       if (alias->symver)
     552            0 :         do_assemble_symver (alias->decl,
     553              :                             DECL_ASSEMBLER_NAME (decl));
     554         4970 :       else if (!alias->transparent_alias)
     555         4970 :         do_assemble_alias (alias->decl,
     556              :                            DECL_ASSEMBLER_NAME (decl));
     557         4970 :       alias->assemble_aliases ();
     558              :     }
     559      2833355 : }
     560              : 
     561              : /* Output one variable, if necessary.  Return whether we output it.  */
     562              : 
     563              : bool
     564      2835674 : varpool_node::assemble_decl (void)
     565              : {
     566              :   /* Aliases are output when their target is produced or by
     567              :      output_weakrefs.  */
     568      2835674 :   if (alias)
     569              :     return false;
     570              : 
     571              :   /* Constant pool is output from RTL land when the reference
     572              :      survive till this level.  */
     573      2830701 :   if (DECL_IN_CONSTANT_POOL (decl) && TREE_ASM_WRITTEN (decl))
     574              :     return false;
     575              : 
     576              :   /* Decls with VALUE_EXPR should not be in the varpool at all.  They
     577              :      are not real variables, but just info for debugging and codegen.
     578              :      Unfortunately at the moment emutls is not updating varpool correctly
     579              :      after turning real vars into value_expr vars.  */
     580      2828565 :   if (DECL_HAS_VALUE_EXPR_P (decl)
     581      2828565 :       && !targetm.have_tls)
     582              :     return false;
     583              : 
     584              :   /* Hard register vars do not need to be output.  */
     585      2828565 :   if (DECL_HARD_REGISTER (decl))
     586              :     return false;
     587              : 
     588      2828565 :   gcc_checking_assert (!TREE_ASM_WRITTEN (decl)
     589              :                        && VAR_P (decl)
     590              :                        && !DECL_HAS_VALUE_EXPR_P (decl));
     591              : 
     592      2828565 :   if (!in_other_partition
     593      2828565 :       && !DECL_EXTERNAL (decl))
     594              :     {
     595      2828385 :       get_constructor ();
     596      2828385 :       assemble_variable (decl, 0, 1, 0);
     597      2828385 :       gcc_assert (TREE_ASM_WRITTEN (decl));
     598      2828385 :       gcc_assert (definition);
     599      2828385 :       assemble_aliases ();
     600              :       /* After the parser has generated debugging information, augment
     601              :          this information with any new location/etc information that may
     602              :          have become available after the compilation proper.  */
     603      2828385 :       debug_hooks->late_global_decl (decl);
     604      2828385 :       return true;
     605              :     }
     606              : 
     607              :   return false;
     608              : }
     609              : 
     610              : /* Add NODE to queue starting at FIRST.
     611              :    The queue is linked via AUX pointers and terminated by pointer to 1.  */
     612              : 
     613              : static void
     614      4724767 : enqueue_node (varpool_node *node, varpool_node **first)
     615              : {
     616      4724767 :   if (node->aux)
     617              :     return;
     618      2830935 :   gcc_checking_assert (*first);
     619      2830935 :   node->aux = *first;
     620      2830935 :   *first = node;
     621              : }
     622              : 
     623              : /* Optimization of function bodies might've rendered some variables as
     624              :    unnecessary so we want to avoid these from being compiled.  Re-do
     625              :    reachability starting from variables that are either externally visible
     626              :    or was referred from the asm output routines.  */
     627              : 
     628              : void
     629       232352 : symbol_table::remove_unreferenced_decls (void)
     630              : {
     631       232352 :   varpool_node *next, *node;
     632       232352 :   varpool_node *first = (varpool_node *)(void *)1;
     633       232352 :   int i;
     634       232352 :   ipa_ref *ref = NULL;
     635       232352 :   hash_set<varpool_node *> referenced;
     636              : 
     637       232352 :   if (seen_error ())
     638            0 :     return;
     639              : 
     640       232352 :   if (dump_file)
     641           72 :     fprintf (dump_file, "Trivially needed variables:");
     642      3119534 :   FOR_EACH_DEFINED_VARIABLE (node)
     643              :     {
     644      2887182 :       if (node->analyzed
     645      2887182 :           && (!node->can_remove_if_no_refs_p ()
     646              :               /* We just expanded all function bodies.  See if any of
     647              :                  them needed the variable.  */
     648      1393242 :               || DECL_RTL_SET_P (node->decl)))
     649              :         {
     650      2218630 :           enqueue_node (node, &first);
     651      2218630 :           if (dump_file)
     652           59 :             fprintf (dump_file, " %s", node->dump_asm_name ());
     653              :         }
     654              :     }
     655      3063287 :   while (first != (varpool_node *)(void *)1)
     656              :     {
     657      2830935 :       node = first;
     658      2830935 :       first = (varpool_node *)first->aux;
     659              : 
     660      2830935 :       if (node->same_comdat_group)
     661              :         {
     662              :           symtab_node *next;
     663       209786 :           for (next = node->same_comdat_group;
     664       219357 :                next != node;
     665       209786 :                next = next->same_comdat_group)
     666              :             {
     667       419572 :               varpool_node *vnext = dyn_cast <varpool_node *> (next);
     668       419572 :               if (vnext && vnext->analyzed && !next->comdat_local_p ())
     669       209780 :                 enqueue_node (vnext, &first);
     670              :             }
     671              :         }
     672      9364381 :       for (i = 0; node->iterate_reference (i, ref); i++)
     673              :         {
     674      3470159 :           varpool_node *vnode = dyn_cast <varpool_node *> (ref->referred);
     675      3470159 :           if (vnode
     676      2541652 :               && !vnode->in_other_partition
     677      2541645 :               && (!DECL_EXTERNAL (ref->referred->decl)
     678       245281 :                   || vnode->alias)
     679      5766523 :               && vnode->analyzed)
     680      2296357 :             enqueue_node (vnode, &first);
     681              :           else
     682              :             {
     683      1173802 :               if (vnode)
     684       245295 :                 referenced.add (vnode);
     685      1173802 :               while (vnode && vnode->alias && vnode->definition)
     686              :                 {
     687            0 :                   vnode = vnode->get_alias_target ();
     688            0 :                   gcc_checking_assert (vnode);
     689            0 :                   referenced.add (vnode);
     690              :                 }
     691              :             }
     692              :         }
     693              :     }
     694       232352 :   if (dump_file)
     695           72 :     fprintf (dump_file, "\nRemoving variables:");
     696      3119534 :   for (node = first_defined_variable (); node; node = next)
     697              :     {
     698      2887182 :       next = next_defined_variable (node);
     699      2887182 :       if (!node->aux && !node->no_reorder)
     700              :         {
     701        56246 :           if (dump_file)
     702            0 :             fprintf (dump_file, " %s", node->dump_asm_name ());
     703        56246 :           if (referenced.contains(node))
     704            0 :             node->remove_initializer ();
     705              :           else
     706        56246 :             node->remove ();
     707              :         }
     708              :     }
     709              : 
     710       232352 :   if (dump_file)
     711           72 :     fprintf (dump_file, "\n");
     712       232352 : }
     713              : 
     714              : /* For variables in named sections make sure get_variable_section
     715              :    is called before we switch to those sections.  Then section
     716              :    conflicts between read-only and read-only requiring relocations
     717              :    sections can be resolved.  */
     718              : void
     719      2823394 : varpool_node::finalize_named_section_flags (void)
     720              : {
     721      2823394 :   if (!TREE_ASM_WRITTEN (decl)
     722      2821525 :       && !alias
     723      2816585 :       && !in_other_partition
     724      2816585 :       && !DECL_EXTERNAL (decl)
     725      2816549 :       && VAR_P (decl)
     726      2816549 :       && !DECL_HAS_VALUE_EXPR_P (decl)
     727      5639943 :       && get_section ())
     728      1432565 :     get_variable_section (decl, false);
     729      2823394 : }
     730              : 
     731              : /* Output all variables enqueued to be assembled.  */
     732              : bool
     733       232638 : symbol_table::output_variables (void)
     734              : {
     735       232638 :   bool changed = false;
     736       232638 :   varpool_node *node;
     737              : 
     738       232638 :   if (seen_error ())
     739              :     return false;
     740              : 
     741       232352 :   remove_unreferenced_decls ();
     742              : 
     743       232352 :   timevar_push (TV_VAROUT);
     744              : 
     745      3063288 :   FOR_EACH_DEFINED_VARIABLE (node)
     746              :     {
     747              :       /* Handled in output_in_order.  */
     748      2830936 :       if (node->no_reorder)
     749       998855 :         continue;
     750              : 
     751      1832081 :       node->finalize_named_section_flags ();
     752              :     }
     753              : 
     754              :   /* There is a similar loop in output_in_order.  Please keep them in sync.  */
     755      3357007 :   FOR_EACH_VARIABLE (node)
     756              :     {
     757              :       /* Handled in output_in_order.  */
     758      3124655 :       if (node->no_reorder)
     759       999498 :         continue;
     760      2125157 :       if (DECL_HARD_REGISTER (node->decl)
     761      2125157 :           || DECL_HAS_VALUE_EXPR_P (node->decl))
     762           62 :         continue;
     763      2125095 :       if (node->definition)
     764      1832019 :         changed |= node->assemble_decl ();
     765              :       else
     766       293076 :         assemble_undefined_decl (node->decl);
     767              :     }
     768       232352 :   timevar_pop (TV_VAROUT);
     769       232352 :   return changed;
     770              : }
     771              : 
     772              : /* Attempt to mark ALIAS as an alias to DECL.  Return TRUE if successful.
     773              :    Extra name aliases are output whenever DECL is output.  */
     774              : 
     775              : varpool_node *
     776        12472 : varpool_node::create_alias (tree alias, tree decl)
     777              : {
     778        12472 :   varpool_node *alias_node;
     779              : 
     780        12472 :   gcc_assert (VAR_P (decl));
     781        12472 :   gcc_assert (VAR_P (alias));
     782        12472 :   alias_node = varpool_node::get_create (alias);
     783        12472 :   alias_node->alias = true;
     784        12472 :   alias_node->definition = true;
     785        12472 :   alias_node->semantic_interposition = flag_semantic_interposition;
     786        12472 :   alias_node->alias_target = decl;
     787        12472 :   if (lookup_attribute ("weakref", DECL_ATTRIBUTES (alias)) != NULL)
     788           11 :     alias_node->weakref = alias_node->transparent_alias = true;
     789        12472 :   return alias_node;
     790              : }
     791              : 
     792              : /* Attempt to mark ALIAS as an alias to DECL.  Return TRUE if successful.
     793              :    Extra name aliases are output whenever DECL is output.  */
     794              : 
     795              : varpool_node *
     796           54 : varpool_node::create_extra_name_alias (tree alias, tree decl)
     797              : {
     798           54 :   varpool_node *alias_node;
     799              : 
     800              :   /* If aliases aren't supported by the assembler, fail.  */
     801           54 :   if (!TARGET_SUPPORTS_ALIASES)
     802              :     return NULL;
     803              : 
     804           54 :   alias_node = varpool_node::create_alias (alias, decl);
     805           54 :   alias_node->cpp_implicit_alias = true;
     806              : 
     807              :   /* Extra name alias mechanism creates aliases really late
     808              :      via DECL_ASSEMBLER_NAME mechanism.
     809              :      This is unfortunate because they are not going through the
     810              :      standard channels.  Ensure they get output.  */
     811           54 :   if (symtab->cpp_implicit_aliases_done)
     812           54 :     alias_node->resolve_alias (varpool_node::get_create (decl));
     813           54 :   return alias_node;
     814              : }
     815              : 
     816              : /* Worker for call_for_symbol_and_aliases.  */
     817              : 
     818              : bool
     819         6823 : varpool_node::call_for_symbol_and_aliases_1 (bool (*callback) (varpool_node *,
     820              :                                                                void *),
     821              :                                              void *data,
     822              :                                              bool include_overwritable)
     823              : {
     824         6823 :   ipa_ref *ref;
     825              : 
     826        29573 :   FOR_EACH_ALIAS (this, ref)
     827              :     {
     828        22750 :       varpool_node *alias = dyn_cast <varpool_node *> (ref->referring);
     829        22750 :       if (include_overwritable
     830        22750 :           || alias->get_availability () > AVAIL_INTERPOSABLE)
     831        22750 :         if (alias->call_for_symbol_and_aliases (callback, data,
     832              :                                                 include_overwritable))
     833              :           return true;
     834              :     }
     835              :   return false;
     836              : }
        

Generated by: LCOV version 2.4-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.