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-02-28 14:20:25 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       300690 : symbol_table::add_varpool_removal_hook (varpool_node_hook hook, void *data)
      54              : {
      55       300690 :   varpool_node_hook_list *entry;
      56       601380 :   varpool_node_hook_list **ptr = &m_first_varpool_removal_hook;
      57              : 
      58       300690 :   entry = (varpool_node_hook_list *) xmalloc (sizeof (*entry));
      59       300690 :   entry->hook = hook;
      60       300690 :   entry->data = data;
      61       300690 :   entry->next = NULL;
      62       308482 :   while (*ptr)
      63         7792 :     ptr = &(*ptr)->next;
      64       300690 :   *ptr = entry;
      65       300690 :   return entry;
      66              : }
      67              : 
      68              : /* Remove ENTRY from the list of hooks called on removing nodes.  */
      69              : void
      70       287368 : symbol_table::remove_varpool_removal_hook (varpool_node_hook_list *entry)
      71              : {
      72       287368 :   varpool_node_hook_list **ptr = &m_first_varpool_removal_hook;
      73              : 
      74       294949 :   while (*ptr != entry)
      75         7581 :     ptr = &(*ptr)->next;
      76       287368 :   *ptr = entry->next;
      77       287368 :   free (entry);
      78       287368 : }
      79              : 
      80              : /* Call all node removal hooks.  */
      81              : void
      82     36766325 : symbol_table::call_varpool_removal_hooks (varpool_node *node)
      83              : {
      84     36766325 :   varpool_node_hook_list *entry = m_first_varpool_removal_hook;
      85     44956231 :   while (entry)
      86              :   {
      87      8189906 :     entry->hook (node, entry->data);
      88      8189906 :     entry = entry->next;
      89              :   }
      90     36766325 : }
      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         2371 : symbol_table::call_varpool_insertion_hooks (varpool_node *node)
     124              : {
     125         2371 :   varpool_node_hook_list *entry = m_first_varpool_insertion_hook;
     126         2371 :   while (entry)
     127              :   {
     128            0 :     entry->hook (node, entry->data);
     129            0 :     entry = entry->next;
     130              :   }
     131         2371 : }
     132              : 
     133              : /* Allocate new callgraph node and insert it into basic data structures.  */
     134              : 
     135              : varpool_node *
     136     40127287 : varpool_node::create_empty (void)
     137              : {
     138     40127287 :   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    291331427 : varpool_node::get_create (tree decl)
     144              : {
     145    291331427 :   varpool_node *node = varpool_node::get (decl);
     146    291331427 :   gcc_checking_assert (VAR_P (decl));
     147    291331427 :   if (node)
     148              :     return node;
     149              : 
     150     40057001 :   node = varpool_node::create_empty ();
     151     40057001 :   node->decl = decl;
     152              : 
     153     40018628 :   if ((flag_openacc || flag_openmp)
     154     40215587 :       && 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     40057001 :   node->register_symbol ();
     166     40057001 :   return node;
     167              : }
     168              : 
     169              : /* Remove variable from symbol table.  */
     170              : 
     171              : void
     172     36766325 : varpool_node::remove (void)
     173              : {
     174     36766325 :   symtab->call_varpool_removal_hooks (this);
     175     36766325 :   lto_free_function_in_decl_state_for_node (this);
     176              : 
     177              :   /* When streaming we can have multiple nodes associated with decl.  */
     178     36766325 :   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     71236068 :   else if (DECL_INITIAL (decl) && DECL_INITIAL (decl) != error_mark_node
     183     71234503 :            && !ctor_useable_for_folding_p ())
     184         3668 :     remove_initializer ();
     185              : 
     186     36766325 :   unregister (NULL);
     187     36766325 :   ggc_free (this);
     188     36766325 : }
     189              : 
     190              : /* Remove node initializer when it is no longer needed.  */
     191              : void
     192      1990951 : varpool_node::remove_initializer (void)
     193              : {
     194      1990951 :   if (DECL_INITIAL (decl)
     195         4205 :       && !DECL_IN_CONSTANT_POOL (decl)
     196              :       /* Keep vtables for BINFO folding.  */
     197         4205 :       && !DECL_VIRTUAL_P (decl)
     198              :       /* FIXME: http://gcc.gnu.org/PR55395 */
     199         3984 :       && 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      1994190 :       && symtab->state != LTO_STREAMING)
     205         3239 :     DECL_INITIAL (decl) = error_mark_node;
     206      1990951 : }
     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      7317410 : varpool_node::get_constructor (void)
     276              : {
     277      7317410 :   lto_file_decl_data *file_data;
     278      7317410 :   const char *data, *name;
     279      7317410 :   size_t len;
     280              : 
     281      7317410 :   if (DECL_INITIAL (decl) != error_mark_node
     282         7643 :       || !in_lto_p
     283      7325049 :       || !lto_file_data)
     284      7309771 :     return DECL_INITIAL (decl);
     285              : 
     286         7639 :   timevar_push (TV_IPA_LTO_CTORS_IN);
     287              : 
     288         7639 :   file_data = lto_file_data;
     289         7639 :   name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
     290              : 
     291              :   /* We may have renamed the declaration, e.g., a static function.  */
     292         7639 :   name = lto_get_decl_name_mapping (file_data, name);
     293         7639 :   struct lto_in_decl_state *decl_state
     294         7639 :          = lto_get_function_in_decl_state (file_data, decl);
     295              : 
     296        15278 :   data = lto_get_section_data (file_data, LTO_section_function_body,
     297         7639 :                                name, order - file_data->order_base,
     298         7639 :                                &len, decl_state->compressed);
     299         7639 :   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         7639 :   if (!quiet_flag)
     305            0 :     fprintf (stderr, " in:%s", IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
     306         7639 :   lto_input_variable_constructor (file_data, this, data);
     307         7639 :   gcc_assert (DECL_INITIAL (decl) != error_mark_node);
     308         7639 :   lto_stats.num_function_bodies++;
     309         7639 :   lto_free_section_data (file_data, LTO_section_function_body, name,
     310         7639 :                          data, len, decl_state->compressed);
     311         7639 :   lto_free_function_in_decl_state_for_node (this);
     312         7639 :   timevar_pop (TV_IPA_LTO_CTORS_IN);
     313         7639 :   return DECL_INITIAL (decl);
     314              : }
     315              : 
     316              : /* Return true if variable has constructor that can be used for folding.  */
     317              : 
     318              : bool
     319     73325516 : varpool_node::ctor_useable_for_folding_p (void)
     320              : {
     321     73325516 :   varpool_node *real_node = this;
     322              : 
     323     73325516 :   if (real_node->alias && real_node->definition)
     324       247749 :     real_node = ultimate_alias_target ();
     325              : 
     326     73325516 :   if (TREE_CODE (decl) == CONST_DECL
     327     73325516 :       || DECL_IN_CONSTANT_POOL (decl))
     328              :     return true;
     329     73324984 :   if (TREE_THIS_VOLATILE (decl))
     330              :     return false;
     331              : 
     332              :   /* Avoid attempts to load constructors that was not streamed.  */
     333       857580 :   if (in_lto_p && DECL_INITIAL (real_node->decl) == error_mark_node
     334     73359630 :       && real_node->body_removed)
     335              :     return false;
     336              : 
     337              :   /* If we do not have a constructor, we can't use it.  */
     338     73287384 :   if (DECL_INITIAL (real_node->decl) == error_mark_node
     339     73287384 :       && !real_node->lto_file_data)
     340              :     return false;
     341              : 
     342              :   /* Folding may cross TU boundaries.  */
     343     73287233 :   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     73287233 :   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      1344094 :       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     71943139 :   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     35713460 :   if ((!DECL_INITIAL (real_node->decl)
     374     34675419 :        || (DECL_WEAK (decl) && !DECL_COMDAT (decl)))
     375     35714066 :       && ((DECL_EXTERNAL (decl) && !in_other_partition)
     376         7104 :           || decl_replaceable_p (decl, semantic_interposition)))
     377      1032263 :     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    145438813 : ctor_for_folding (tree decl)
     398              : {
     399    145438813 :   varpool_node *node, *real_node;
     400    145438813 :   tree real_decl;
     401              : 
     402    145438813 :   if (!VAR_P (decl) && TREE_CODE (decl) != CONST_DECL)
     403      4438303 :     return error_mark_node;
     404              : 
     405    141000510 :   if (TREE_CODE (decl) == CONST_DECL
     406    141000510 :       || DECL_IN_CONSTANT_POOL (decl))
     407        85931 :     return DECL_INITIAL (decl);
     408              : 
     409    140914579 :   if (TREE_THIS_VOLATILE (decl))
     410      2157310 :     return error_mark_node;
     411              : 
     412              :   /* Do not care about automatic variables.  Those are never initialized
     413              :      anyway, because gimplifier expands the code.  */
     414    138757269 :   if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
     415              :     {
     416     99058517 :       gcc_assert (!TREE_PUBLIC (decl));
     417              :       /* Unless this is called during FE folding.  */
     418     99058517 :       if (cfun
     419     99053853 :           && (cfun->curr_properties & (PROP_gimple | PROP_rtl)) == 0
     420      5809977 :           && TREE_READONLY (decl)
     421        16595 :           && !TREE_SIDE_EFFECTS (decl)
     422     99075112 :           && DECL_INITIAL (decl))
     423          423 :         return DECL_INITIAL (decl);
     424     99058094 :       return error_mark_node;
     425              :     }
     426              : 
     427     39698752 :   gcc_assert (VAR_P (decl));
     428              : 
     429     39698752 :   real_node = node = varpool_node::get (decl);
     430     39698752 :   if (node)
     431              :     {
     432     39137699 :       real_node = node->ultimate_alias_target ();
     433     39137699 :       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     39698752 :   if (decl != real_decl)
     444              :     {
     445       247445 :       gcc_assert (!DECL_INITIAL (decl)
     446              :                   || (node->alias && node->get_alias_target () == real_node)
     447              :                   || DECL_INITIAL (decl) == error_mark_node);
     448       247445 :       while (node->transparent_alias && node->analyzed)
     449              :         {
     450            0 :           node = node->get_alias_target ();
     451            0 :           decl = node->decl;
     452              :         }
     453              :     }
     454              : 
     455     39698752 :   if ((!DECL_VIRTUAL_P (real_decl)
     456       687929 :        || DECL_INITIAL (real_decl) == error_mark_node
     457       687403 :        || !DECL_INITIAL (real_decl))
     458     39770924 :       && (!node || !node->ctor_useable_for_folding_p ()))
     459     37606957 :     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      2091795 :   if (DECL_INITIAL (real_decl) != error_mark_node
     464      2091795 :       || !in_lto_p)
     465      2090436 :     return DECL_INITIAL (real_decl);
     466         1359 :   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         2371 : varpool_node::add (tree decl)
     475              : {
     476         2371 :   varpool_node *node;
     477         2371 :   varpool_node::finalize_decl (decl);
     478         2371 :   node = varpool_node::get_create (decl);
     479         2371 :   symtab->call_varpool_insertion_hooks (node);
     480         2371 :   if (node->externally_visible_p ())
     481         2358 :     node->externally_visible = true;
     482         2371 :   if (lookup_attribute ("no_reorder", DECL_ATTRIBUTES (decl)))
     483            0 :     node->no_reorder = 1;
     484         2371 : }
     485              : 
     486              : /* Return variable availability.  See cgraph.h for description of individual
     487              :    return values.  */
     488              : enum availability
     489    170189865 : varpool_node::get_availability (symtab_node *ref)
     490              : {
     491    170189865 :   if (!definition && !in_other_partition)
     492              :     return AVAIL_NOT_AVAILABLE;
     493    146980613 :   if (!TREE_PUBLIC (decl))
     494              :     return AVAIL_AVAILABLE;
     495     51310369 :   if (DECL_IN_CONSTANT_POOL (decl)
     496     51310369 :       || DECL_VIRTUAL_P (decl))
     497              :     return AVAIL_AVAILABLE;
     498     51251729 :   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     51251729 :       || (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     51251729 :   if (decl_replaceable_p (decl, semantic_interposition)
     516     51251729 :       || (DECL_EXTERNAL (decl) && !in_other_partition))
     517              :     return AVAIL_INTERPOSABLE;
     518              :   return AVAIL_AVAILABLE;
     519              : }
     520              : 
     521              : void
     522      3060772 : 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      3060772 :   if (!analyzed)
     528              :     {
     529      3060772 :       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      3060772 :       align_variable (decl, 0);
     533              :     }
     534      3060772 :   if (alias)
     535          135 :     resolve_alias (varpool_node::get (alias_target));
     536      3060637 :   else if (DECL_INITIAL (decl))
     537      2004298 :     record_references_in_initializer (decl, analyzed);
     538      3060772 :   analyzed = true;
     539      3060772 : }
     540              : 
     541              : /* Assemble thunks and aliases associated to varpool node.  */
     542              : 
     543              : void
     544      2830271 : varpool_node::assemble_aliases (void)
     545              : {
     546      2830271 :   ipa_ref *ref;
     547              : 
     548      2835241 :   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      2830271 : }
     560              : 
     561              : /* Output one variable, if necessary.  Return whether we output it.  */
     562              : 
     563              : bool
     564      2832394 : varpool_node::assemble_decl (void)
     565              : {
     566              :   /* Aliases are output when their target is produced or by
     567              :      output_weakrefs.  */
     568      2832394 :   if (alias)
     569              :     return false;
     570              : 
     571              :   /* Constant pool is output from RTL land when the reference
     572              :      survive till this level.  */
     573      2827421 :   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      2825481 :   if (DECL_HAS_VALUE_EXPR_P (decl)
     581      2825481 :       && !targetm.have_tls)
     582              :     return false;
     583              : 
     584              :   /* Hard register vars do not need to be output.  */
     585      2825481 :   if (DECL_HARD_REGISTER (decl))
     586              :     return false;
     587              : 
     588      2825481 :   gcc_checking_assert (!TREE_ASM_WRITTEN (decl)
     589              :                        && VAR_P (decl)
     590              :                        && !DECL_HAS_VALUE_EXPR_P (decl));
     591              : 
     592      2825481 :   if (!in_other_partition
     593      2825481 :       && !DECL_EXTERNAL (decl))
     594              :     {
     595      2825301 :       get_constructor ();
     596      2825301 :       assemble_variable (decl, 0, 1, 0);
     597      2825301 :       gcc_assert (TREE_ASM_WRITTEN (decl));
     598      2825301 :       gcc_assert (definition);
     599      2825301 :       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      2825301 :       debug_hooks->late_global_decl (decl);
     604      2825301 :       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      4721214 : enqueue_node (varpool_node *node, varpool_node **first)
     615              : {
     616      4721214 :   if (node->aux)
     617              :     return;
     618      2827655 :   gcc_checking_assert (*first);
     619      2827655 :   node->aux = *first;
     620      2827655 :   *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       230133 : symbol_table::remove_unreferenced_decls (void)
     630              : {
     631       230133 :   varpool_node *next, *node;
     632       230133 :   varpool_node *first = (varpool_node *)(void *)1;
     633       230133 :   int i;
     634       230133 :   ipa_ref *ref = NULL;
     635       230133 :   hash_set<varpool_node *> referenced;
     636              : 
     637       230133 :   if (seen_error ())
     638            0 :     return;
     639              : 
     640       230133 :   if (dump_file)
     641           72 :     fprintf (dump_file, "Trivially needed variables:");
     642      3113596 :   FOR_EACH_DEFINED_VARIABLE (node)
     643              :     {
     644      2883463 :       if (node->analyzed
     645      2883463 :           && (!node->can_remove_if_no_refs_p ()
     646              :               /* We just expanded all function bodies.  See if any of
     647              :                  them needed the variable.  */
     648      1390434 :               || DECL_RTL_SET_P (node->decl)))
     649              :         {
     650      2215278 :           enqueue_node (node, &first);
     651      2215278 :           if (dump_file)
     652           59 :             fprintf (dump_file, " %s", node->dump_asm_name ());
     653              :         }
     654              :     }
     655      3057788 :   while (first != (varpool_node *)(void *)1)
     656              :     {
     657      2827655 :       node = first;
     658      2827655 :       first = (varpool_node *)first->aux;
     659              : 
     660      2827655 :       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      9355744 :       for (i = 0; node->iterate_reference (i, ref); i++)
     673              :         {
     674      3470301 :           varpool_node *vnode = dyn_cast <varpool_node *> (ref->referred);
     675      3470301 :           if (vnode
     676      2541623 :               && !vnode->in_other_partition
     677      2541616 :               && (!DECL_EXTERNAL (ref->referred->decl)
     678       245453 :                   || vnode->alias)
     679      5766464 :               && vnode->analyzed)
     680      2296156 :             enqueue_node (vnode, &first);
     681              :           else
     682              :             {
     683      1174145 :               if (vnode)
     684       245467 :                 referenced.add (vnode);
     685      1174145 :               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       230133 :   if (dump_file)
     695           72 :     fprintf (dump_file, "\nRemoving variables:");
     696      3113596 :   for (node = first_defined_variable (); node; node = next)
     697              :     {
     698      2883463 :       next = next_defined_variable (node);
     699      2883463 :       if (!node->aux && !node->no_reorder)
     700              :         {
     701        55807 :           if (dump_file)
     702            0 :             fprintf (dump_file, " %s", node->dump_asm_name ());
     703        55807 :           if (referenced.contains(node))
     704            0 :             node->remove_initializer ();
     705              :           else
     706        55807 :             node->remove ();
     707              :         }
     708              :     }
     709              : 
     710       230133 :   if (dump_file)
     711           72 :     fprintf (dump_file, "\n");
     712       230133 : }
     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      2820162 : varpool_node::finalize_named_section_flags (void)
     720              : {
     721      2820162 :   if (!TREE_ASM_WRITTEN (decl)
     722      2818489 :       && !alias
     723      2813549 :       && !in_other_partition
     724      2813549 :       && !DECL_EXTERNAL (decl)
     725      2813513 :       && VAR_P (decl)
     726      2813513 :       && !DECL_HAS_VALUE_EXPR_P (decl)
     727      5633675 :       && get_section ())
     728      1432445 :     get_variable_section (decl, false);
     729      2820162 : }
     730              : 
     731              : /* Output all variables enqueued to be assembled.  */
     732              : bool
     733       230419 : symbol_table::output_variables (void)
     734              : {
     735       230419 :   bool changed = false;
     736       230419 :   varpool_node *node;
     737              : 
     738       230419 :   if (seen_error ())
     739              :     return false;
     740              : 
     741       230133 :   remove_unreferenced_decls ();
     742              : 
     743       230133 :   timevar_push (TV_VAROUT);
     744              : 
     745      3057789 :   FOR_EACH_DEFINED_VARIABLE (node)
     746              :     {
     747              :       /* Handled in output_in_order.  */
     748      2827656 :       if (node->no_reorder)
     749       997651 :         continue;
     750              : 
     751      1830005 :       node->finalize_named_section_flags ();
     752              :     }
     753              : 
     754              :   /* There is a similar loop in output_in_order.  Please keep them in sync.  */
     755      3351635 :   FOR_EACH_VARIABLE (node)
     756              :     {
     757              :       /* Handled in output_in_order.  */
     758      3121502 :       if (node->no_reorder)
     759       998291 :         continue;
     760      2123211 :       if (DECL_HARD_REGISTER (node->decl)
     761      2123211 :           || DECL_HAS_VALUE_EXPR_P (node->decl))
     762           62 :         continue;
     763      2123149 :       if (node->definition)
     764      1829943 :         changed |= node->assemble_decl ();
     765              :       else
     766       293206 :         assemble_undefined_decl (node->decl);
     767              :     }
     768       230133 :   timevar_pop (TV_VAROUT);
     769       230133 :   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        12464 : varpool_node::create_alias (tree alias, tree decl)
     777              : {
     778        12464 :   varpool_node *alias_node;
     779              : 
     780        12464 :   gcc_assert (VAR_P (decl));
     781        12464 :   gcc_assert (VAR_P (alias));
     782        12464 :   alias_node = varpool_node::get_create (alias);
     783        12464 :   alias_node->alias = true;
     784        12464 :   alias_node->definition = true;
     785        12464 :   alias_node->semantic_interposition = flag_semantic_interposition;
     786        12464 :   alias_node->alias_target = decl;
     787        12464 :   if (lookup_attribute ("weakref", DECL_ATTRIBUTES (alias)) != NULL)
     788           11 :     alias_node->weakref = alias_node->transparent_alias = true;
     789        12464 :   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         6815 : varpool_node::call_for_symbol_and_aliases_1 (bool (*callback) (varpool_node *,
     820              :                                                                void *),
     821              :                                              void *data,
     822              :                                              bool include_overwritable)
     823              : {
     824         6815 :   ipa_ref *ref;
     825              : 
     826        29549 :   FOR_EACH_ALIAS (this, ref)
     827              :     {
     828        22734 :       varpool_node *alias = dyn_cast <varpool_node *> (ref->referring);
     829        22734 :       if (include_overwritable
     830        22734 :           || alias->get_availability () > AVAIL_INTERPOSABLE)
     831        22734 :         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.