123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829 |
- /* Callgraph handling code.
- Copyright (C) 2003-2015 Free Software Foundation, Inc.
- Contributed by Jan Hubicka
- This file is part of GCC.
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
- #include "config.h"
- #include "system.h"
- #include "coretypes.h"
- #include "tm.h"
- #include "hash-set.h"
- #include "machmode.h"
- #include "vec.h"
- #include "double-int.h"
- #include "input.h"
- #include "alias.h"
- #include "symtab.h"
- #include "wide-int.h"
- #include "inchash.h"
- #include "tree.h"
- #include "fold-const.h"
- #include "varasm.h"
- #include "predict.h"
- #include "basic-block.h"
- #include "hash-map.h"
- #include "is-a.h"
- #include "plugin-api.h"
- #include "hard-reg-set.h"
- #include "input.h"
- #include "function.h"
- #include "ipa-ref.h"
- #include "cgraph.h"
- #include "langhooks.h"
- #include "diagnostic-core.h"
- #include "timevar.h"
- #include "debug.h"
- #include "target.h"
- #include "output.h"
- #include "gimple-expr.h"
- #include "flags.h"
- #include "tree-ssa-alias.h"
- #include "gimple.h"
- #include "lto-streamer.h"
- #include "context.h"
- #include "omp-low.h"
- const char * const tls_model_names[]={"none", "emulated",
- "global-dynamic", "local-dynamic",
- "initial-exec", "local-exec"};
- /* List of hooks triggered on varpool_node events. */
- struct varpool_node_hook_list {
- varpool_node_hook hook;
- void *data;
- struct varpool_node_hook_list *next;
- };
- /* Register HOOK to be called with DATA on each removed node. */
- varpool_node_hook_list *
- symbol_table::add_varpool_removal_hook (varpool_node_hook hook, void *data)
- {
- varpool_node_hook_list *entry;
- varpool_node_hook_list **ptr = &m_first_varpool_removal_hook;
- entry = (varpool_node_hook_list *) xmalloc (sizeof (*entry));
- entry->hook = hook;
- entry->data = data;
- entry->next = NULL;
- while (*ptr)
- ptr = &(*ptr)->next;
- *ptr = entry;
- return entry;
- }
- /* Remove ENTRY from the list of hooks called on removing nodes. */
- void
- symbol_table::remove_varpool_removal_hook (varpool_node_hook_list *entry)
- {
- varpool_node_hook_list **ptr = &m_first_varpool_removal_hook;
- while (*ptr != entry)
- ptr = &(*ptr)->next;
- *ptr = entry->next;
- free (entry);
- }
- /* Call all node removal hooks. */
- void
- symbol_table::call_varpool_removal_hooks (varpool_node *node)
- {
- varpool_node_hook_list *entry = m_first_varpool_removal_hook;
- while (entry)
- {
- entry->hook (node, entry->data);
- entry = entry->next;
- }
- }
- /* Register HOOK to be called with DATA on each inserted node. */
- varpool_node_hook_list *
- symbol_table::add_varpool_insertion_hook (varpool_node_hook hook, void *data)
- {
- varpool_node_hook_list *entry;
- varpool_node_hook_list **ptr = &m_first_varpool_insertion_hook;
- entry = (varpool_node_hook_list *) xmalloc (sizeof (*entry));
- entry->hook = hook;
- entry->data = data;
- entry->next = NULL;
- while (*ptr)
- ptr = &(*ptr)->next;
- *ptr = entry;
- return entry;
- }
- /* Remove ENTRY from the list of hooks called on inserted nodes. */
- void
- symbol_table::remove_varpool_insertion_hook (varpool_node_hook_list *entry)
- {
- varpool_node_hook_list **ptr = &m_first_varpool_insertion_hook;
- while (*ptr != entry)
- ptr = &(*ptr)->next;
- *ptr = entry->next;
- free (entry);
- }
- /* Call all node insertion hooks. */
- void
- symbol_table::call_varpool_insertion_hooks (varpool_node *node)
- {
- varpool_node_hook_list *entry = m_first_varpool_insertion_hook;
- while (entry)
- {
- entry->hook (node, entry->data);
- entry = entry->next;
- }
- }
- /* Allocate new callgraph node and insert it into basic data structures. */
- varpool_node *
- varpool_node::create_empty (void)
- {
- varpool_node *node = ggc_cleared_alloc<varpool_node> ();
- node->type = SYMTAB_VARIABLE;
- return node;
- }
- /* Return varpool node assigned to DECL. Create new one when needed. */
- varpool_node *
- varpool_node::get_create (tree decl)
- {
- varpool_node *node = varpool_node::get (decl);
- gcc_checking_assert (TREE_CODE (decl) == VAR_DECL);
- if (node)
- return node;
- node = varpool_node::create_empty ();
- node->decl = decl;
- if ((flag_openacc || flag_openmp) && !DECL_EXTERNAL (decl)
- && lookup_attribute ("omp declare target", DECL_ATTRIBUTES (decl)))
- {
- node->offloadable = 1;
- #ifdef ENABLE_OFFLOADING
- g->have_offload = true;
- if (!in_lto_p)
- vec_safe_push (offload_vars, decl);
- node->force_output = 1;
- #endif
- }
- node->register_symbol ();
- return node;
- }
- /* Remove variable from symbol table. */
- void
- varpool_node::remove (void)
- {
- symtab->call_varpool_removal_hooks (this);
- if (lto_file_data)
- {
- lto_free_function_in_decl_state_for_node (this);
- lto_file_data = NULL;
- }
- /* When streaming we can have multiple nodes associated with decl. */
- if (symtab->state == LTO_STREAMING)
- ;
- /* Keep constructor when it may be used for folding. We remove
- references to external variables before final compilation. */
- else if (DECL_INITIAL (decl) && DECL_INITIAL (decl) != error_mark_node
- && !ctor_useable_for_folding_p ())
- remove_initializer ();
- unregister ();
- ggc_free (this);
- }
- /* Remove node initializer when it is no longer needed. */
- void
- varpool_node::remove_initializer (void)
- {
- if (DECL_INITIAL (decl)
- && !DECL_IN_CONSTANT_POOL (decl)
- /* Keep vtables for BINFO folding. */
- && !DECL_VIRTUAL_P (decl)
- /* FIXME: http://gcc.gnu.org/PR55395 */
- && debug_info_level == DINFO_LEVEL_NONE
- /* When doing declaration merging we have duplicate
- entries for given decl. Do not attempt to remove
- the boides, or we will end up remiving
- wrong one. */
- && symtab->state != LTO_STREAMING)
- DECL_INITIAL (decl) = error_mark_node;
- }
- /* Dump given varpool node to F. */
- void
- varpool_node::dump (FILE *f)
- {
- dump_base (f);
- fprintf (f, " Availability: %s\n",
- symtab->function_flags_ready
- ? cgraph_availability_names[get_availability ()]
- : "not-ready");
- fprintf (f, " Varpool flags:");
- if (DECL_INITIAL (decl))
- fprintf (f, " initialized");
- if (output)
- fprintf (f, " output");
- if (used_by_single_function)
- fprintf (f, " used-by-single-function");
- if (need_bounds_init)
- fprintf (f, " need-bounds-init");
- if (TREE_READONLY (decl))
- fprintf (f, " read-only");
- if (ctor_useable_for_folding_p ())
- fprintf (f, " const-value-known");
- if (writeonly)
- fprintf (f, " write-only");
- if (tls_model)
- fprintf (f, " tls-%s", tls_model_names [tls_model]);
- fprintf (f, "\n");
- }
- /* Dump given varpool node to stderr. */
- void varpool_node::debug (void)
- {
- varpool_node::dump (stderr);
- }
- /* Dump the variable pool to F. */
- void
- varpool_node::dump_varpool (FILE *f)
- {
- varpool_node *node;
- fprintf (f, "variable pool:\n\n");
- FOR_EACH_VARIABLE (node)
- node->dump (f);
- }
- /* Dump the variable pool to stderr. */
- DEBUG_FUNCTION void
- varpool_node::debug_varpool (void)
- {
- dump_varpool (stderr);
- }
- /* Given an assembler name, lookup node. */
- varpool_node *
- varpool_node::get_for_asmname (tree asmname)
- {
- if (symtab_node *node = symtab_node::get_for_asmname (asmname))
- return dyn_cast <varpool_node *> (node);
- else
- return NULL;
- }
- /* When doing LTO, read variable's constructor from disk if
- it is not already present. */
- tree
- varpool_node::get_constructor (void)
- {
- lto_file_decl_data *file_data;
- const char *data, *name;
- size_t len;
- if (DECL_INITIAL (decl) != error_mark_node
- || !in_lto_p
- || !lto_file_data)
- return DECL_INITIAL (decl);
- timevar_push (TV_IPA_LTO_CTORS_IN);
- file_data = lto_file_data;
- name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
- /* We may have renamed the declaration, e.g., a static function. */
- name = lto_get_decl_name_mapping (file_data, name);
- data = lto_get_section_data (file_data, LTO_section_function_body,
- name, &len);
- if (!data)
- fatal_error (input_location, "%s: section %s is missing",
- file_data->file_name,
- name);
- lto_input_variable_constructor (file_data, this, data);
- gcc_assert (DECL_INITIAL (decl) != error_mark_node);
- lto_stats.num_function_bodies++;
- lto_free_section_data (file_data, LTO_section_function_body, name,
- data, len);
- lto_free_function_in_decl_state_for_node (this);
- timevar_pop (TV_IPA_LTO_CTORS_IN);
- return DECL_INITIAL (decl);
- }
- /* Return true if variable has constructor that can be used for folding. */
- bool
- varpool_node::ctor_useable_for_folding_p (void)
- {
- varpool_node *real_node = this;
- if (real_node->alias && real_node->definition)
- real_node = ultimate_alias_target ();
- if (TREE_CODE (decl) == CONST_DECL
- || DECL_IN_CONSTANT_POOL (decl))
- return true;
- if (TREE_THIS_VOLATILE (decl))
- return false;
- /* If we do not have a constructor, we can't use it. */
- if (DECL_INITIAL (real_node->decl) == error_mark_node
- && !real_node->lto_file_data)
- return false;
- /* Avoid attempts to load constructors that was not streamed. */
- if (flag_ltrans && DECL_INITIAL (real_node->decl) == error_mark_node
- && real_node->body_removed)
- return false;
- /* Vtables are defined by their types and must match no matter of interposition
- rules. */
- if (DECL_VIRTUAL_P (decl))
- {
- /* The C++ front end creates VAR_DECLs for vtables of typeinfo
- classes not defined in the current TU so that it can refer
- to them from typeinfo objects. Avoid returning NULL_TREE. */
- return DECL_INITIAL (real_node->decl) != NULL;
- }
- /* Alias of readonly variable is also readonly, since the variable is stored
- in readonly memory. We also accept readonly aliases of non-readonly
- locations assuming that user knows what he is asking for. */
- if (!TREE_READONLY (decl) && !TREE_READONLY (real_node->decl))
- return false;
- /* Variables declared 'const' without an initializer
- have zero as the initializer if they may not be
- overridden at link or run time.
- It is actually requirement for C++ compiler to optimize const variables
- consistently. As a GNU extension, do not enfore this rule for user defined
- weak variables, so we support interposition on:
- static const int dummy = 0;
- extern const int foo __attribute__((__weak__, __alias__("dummy")));
- */
- if ((!DECL_INITIAL (real_node->decl)
- || (DECL_WEAK (decl) && !DECL_COMDAT (decl)))
- && (DECL_EXTERNAL (decl) || decl_replaceable_p (decl)))
- return false;
- /* Variables declared `const' with an initializer are considered
- to not be overwritable with different initializer by default.
- ??? Previously we behaved so for scalar variables but not for array
- accesses. */
- return true;
- }
- /* If DECLARATION is constant variable and its initial value is known
- (so we can do constant folding), return its constructor (DECL_INITIAL).
- This may be an expression or NULL when DECL is initialized to 0.
- Return ERROR_MARK_NODE otherwise.
- In LTO this may actually trigger reading the constructor from disk.
- For this reason varpool_ctor_useable_for_folding_p should be used when
- the actual constructor value is not needed. */
- tree
- ctor_for_folding (tree decl)
- {
- varpool_node *node, *real_node;
- tree real_decl;
- if (TREE_CODE (decl) != VAR_DECL
- && TREE_CODE (decl) != CONST_DECL)
- return error_mark_node;
- /* Static constant bounds are created to be
- used instead of constants and therefore
- do not let folding it. */
- if (POINTER_BOUNDS_P (decl))
- return error_mark_node;
- if (TREE_CODE (decl) == CONST_DECL
- || DECL_IN_CONSTANT_POOL (decl))
- return DECL_INITIAL (decl);
- if (TREE_THIS_VOLATILE (decl))
- return error_mark_node;
- /* Do not care about automatic variables. Those are never initialized
- anyway, because gimplifier exapnds the code. */
- if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
- {
- gcc_assert (!TREE_PUBLIC (decl));
- return error_mark_node;
- }
- gcc_assert (TREE_CODE (decl) == VAR_DECL);
- real_node = node = varpool_node::get (decl);
- if (node)
- {
- real_node = node->ultimate_alias_target ();
- real_decl = real_node->decl;
- }
- else
- real_decl = decl;
- /* See if we are dealing with alias.
- In most cases alias is just alternative symbol pointing to a given
- constructor. This allows us to use interposition rules of DECL
- constructor of REAL_NODE. However weakrefs are special by being just
- alternative name of their target (if defined). */
- if (decl != real_decl)
- {
- gcc_assert (!DECL_INITIAL (decl)
- || (node->alias && node->get_alias_target () == real_node)
- || DECL_INITIAL (decl) == error_mark_node);
- if (node->weakref)
- {
- node = node->get_alias_target ();
- decl = node->decl;
- }
- }
- if ((!DECL_VIRTUAL_P (real_decl)
- || DECL_INITIAL (real_decl) == error_mark_node
- || !DECL_INITIAL (real_decl))
- && (!node || !node->ctor_useable_for_folding_p ()))
- return error_mark_node;
- /* OK, we can return constructor. See if we need to fetch it from disk
- in LTO mode. */
- if (DECL_INITIAL (real_decl) != error_mark_node
- || !in_lto_p)
- return DECL_INITIAL (real_decl);
- return real_node->get_constructor ();
- }
- /* Add the variable DECL to the varpool.
- Unlike finalize_decl function is intended to be used
- by middle end and allows insertion of new variable at arbitrary point
- of compilation. */
- void
- varpool_node::add (tree decl)
- {
- varpool_node *node;
- varpool_node::finalize_decl (decl);
- node = varpool_node::get_create (decl);
- symtab->call_varpool_insertion_hooks (node);
- if (node->externally_visible_p ())
- node->externally_visible = true;
- if (lookup_attribute ("no_reorder", DECL_ATTRIBUTES (decl)))
- node->no_reorder = 1;
- }
- /* Return variable availability. See cgraph.h for description of individual
- return values. */
- enum availability
- varpool_node::get_availability (void)
- {
- if (!definition)
- return AVAIL_NOT_AVAILABLE;
- if (!TREE_PUBLIC (decl))
- return AVAIL_AVAILABLE;
- if (DECL_IN_CONSTANT_POOL (decl)
- || DECL_VIRTUAL_P (decl))
- return AVAIL_AVAILABLE;
- if (alias && weakref)
- {
- enum availability avail;
- ultimate_alias_target (&avail)->get_availability ();
- return avail;
- }
- /* If the variable can be overwritten, return OVERWRITABLE. Takes
- care of at least one notable extension - the COMDAT variables
- used to share template instantiations in C++. */
- if (decl_replaceable_p (decl)
- || DECL_EXTERNAL (decl))
- return AVAIL_INTERPOSABLE;
- return AVAIL_AVAILABLE;
- }
- void
- varpool_node::analyze (void)
- {
- /* When reading back varpool at LTO time, we re-construct the queue in order
- to have "needed" list right by inserting all needed nodes into varpool.
- We however don't want to re-analyze already analyzed nodes. */
- if (!analyzed)
- {
- gcc_assert (!in_lto_p || symtab->function_flags_ready);
- /* Compute the alignment early so function body expanders are
- already informed about increased alignment. */
- align_variable (decl, 0);
- }
- if (alias)
- resolve_alias (varpool_node::get (alias_target));
- else if (DECL_INITIAL (decl))
- record_references_in_initializer (decl, analyzed);
- analyzed = true;
- }
- /* Assemble thunks and aliases associated to varpool node. */
- void
- varpool_node::assemble_aliases (void)
- {
- ipa_ref *ref;
- FOR_EACH_ALIAS (this, ref)
- {
- varpool_node *alias = dyn_cast <varpool_node *> (ref->referring);
- do_assemble_alias (alias->decl,
- DECL_ASSEMBLER_NAME (decl));
- alias->assemble_aliases ();
- }
- }
- /* Output one variable, if necessary. Return whether we output it. */
- bool
- varpool_node::assemble_decl (void)
- {
- /* Aliases are outout when their target is produced or by
- output_weakrefs. */
- if (alias)
- return false;
- /* Constant pool is output from RTL land when the reference
- survive till this level. */
- if (DECL_IN_CONSTANT_POOL (decl) && TREE_ASM_WRITTEN (decl))
- return false;
- /* Decls with VALUE_EXPR should not be in the varpool at all. They
- are not real variables, but just info for debugging and codegen.
- Unfortunately at the moment emutls is not updating varpool correctly
- after turning real vars into value_expr vars. */
- if (DECL_HAS_VALUE_EXPR_P (decl)
- && !targetm.have_tls)
- return false;
- /* Hard register vars do not need to be output. */
- if (DECL_HARD_REGISTER (decl))
- return false;
- gcc_checking_assert (!TREE_ASM_WRITTEN (decl)
- && TREE_CODE (decl) == VAR_DECL
- && !DECL_HAS_VALUE_EXPR_P (decl));
- if (!in_other_partition
- && !DECL_EXTERNAL (decl))
- {
- get_constructor ();
- assemble_variable (decl, 0, 1, 0);
- gcc_assert (TREE_ASM_WRITTEN (decl));
- gcc_assert (definition);
- assemble_aliases ();
- return true;
- }
- return false;
- }
- /* Add NODE to queue starting at FIRST.
- The queue is linked via AUX pointers and terminated by pointer to 1. */
- static void
- enqueue_node (varpool_node *node, varpool_node **first)
- {
- if (node->aux)
- return;
- gcc_checking_assert (*first);
- node->aux = *first;
- *first = node;
- }
- /* Optimization of function bodies might've rendered some variables as
- unnecessary so we want to avoid these from being compiled. Re-do
- reachability starting from variables that are either externally visible
- or was referred from the asm output routines. */
- void
- symbol_table::remove_unreferenced_decls (void)
- {
- varpool_node *next, *node;
- varpool_node *first = (varpool_node *)(void *)1;
- int i;
- ipa_ref *ref = NULL;
- hash_set<varpool_node *> referenced;
- if (seen_error ())
- return;
- if (dump_file)
- fprintf (dump_file, "Trivially needed variables:");
- FOR_EACH_DEFINED_VARIABLE (node)
- {
- if (node->analyzed
- && (!node->can_remove_if_no_refs_p ()
- /* We just expanded all function bodies. See if any of
- them needed the variable. */
- || DECL_RTL_SET_P (node->decl)))
- {
- enqueue_node (node, &first);
- if (dump_file)
- fprintf (dump_file, " %s", node->asm_name ());
- }
- }
- while (first != (varpool_node *)(void *)1)
- {
- node = first;
- first = (varpool_node *)first->aux;
- if (node->same_comdat_group)
- {
- symtab_node *next;
- for (next = node->same_comdat_group;
- next != node;
- next = next->same_comdat_group)
- {
- varpool_node *vnext = dyn_cast <varpool_node *> (next);
- if (vnext && vnext->analyzed && !next->comdat_local_p ())
- enqueue_node (vnext, &first);
- }
- }
- for (i = 0; node->iterate_reference (i, ref); i++)
- {
- varpool_node *vnode = dyn_cast <varpool_node *> (ref->referred);
- if (vnode
- && !vnode->in_other_partition
- && (!DECL_EXTERNAL (ref->referred->decl)
- || vnode->alias)
- && vnode->analyzed)
- enqueue_node (vnode, &first);
- else
- referenced.add (node);
- }
- }
- if (dump_file)
- fprintf (dump_file, "\nRemoving variables:");
- for (node = first_defined_variable (); node; node = next)
- {
- next = next_defined_variable (node);
- if (!node->aux && !node->no_reorder)
- {
- if (dump_file)
- fprintf (dump_file, " %s", node->asm_name ());
- if (referenced.contains(node))
- node->remove_initializer ();
- else
- node->remove ();
- }
- }
- if (dump_file)
- fprintf (dump_file, "\n");
- }
- /* For variables in named sections make sure get_variable_section
- is called before we switch to those sections. Then section
- conflicts between read-only and read-only requiring relocations
- sections can be resolved. */
- void
- varpool_node::finalize_named_section_flags (void)
- {
- if (!TREE_ASM_WRITTEN (decl)
- && !alias
- && !in_other_partition
- && !DECL_EXTERNAL (decl)
- && TREE_CODE (decl) == VAR_DECL
- && !DECL_HAS_VALUE_EXPR_P (decl)
- && get_section ())
- get_variable_section (decl, false);
- }
- /* Output all variables enqueued to be assembled. */
- bool
- symbol_table::output_variables (void)
- {
- bool changed = false;
- varpool_node *node;
- if (seen_error ())
- return false;
- remove_unreferenced_decls ();
- timevar_push (TV_VAROUT);
- FOR_EACH_VARIABLE (node)
- if (!node->definition
- && !DECL_HAS_VALUE_EXPR_P (node->decl)
- && !DECL_HARD_REGISTER (node->decl))
- assemble_undefined_decl (node->decl);
- FOR_EACH_DEFINED_VARIABLE (node)
- {
- /* Handled in output_in_order. */
- if (node->no_reorder)
- continue;
- node->finalize_named_section_flags ();
- }
- FOR_EACH_DEFINED_VARIABLE (node)
- {
- /* Handled in output_in_order. */
- if (node->no_reorder)
- continue;
- if (node->assemble_decl ())
- changed = true;
- }
- timevar_pop (TV_VAROUT);
- return changed;
- }
- /* Attempt to mark ALIAS as an alias to DECL. Return TRUE if successful.
- Extra name aliases are output whenever DECL is output. */
- varpool_node *
- varpool_node::create_alias (tree alias, tree decl)
- {
- varpool_node *alias_node;
- gcc_assert (TREE_CODE (decl) == VAR_DECL);
- gcc_assert (TREE_CODE (alias) == VAR_DECL);
- alias_node = varpool_node::get_create (alias);
- alias_node->alias = true;
- alias_node->definition = true;
- alias_node->alias_target = decl;
- if (lookup_attribute ("weakref", DECL_ATTRIBUTES (alias)) != NULL)
- alias_node->weakref = true;
- return alias_node;
- }
- /* Attempt to mark ALIAS as an alias to DECL. Return TRUE if successful.
- Extra name aliases are output whenever DECL is output. */
- varpool_node *
- varpool_node::create_extra_name_alias (tree alias, tree decl)
- {
- varpool_node *alias_node;
- #ifndef ASM_OUTPUT_DEF
- /* If aliases aren't supported by the assembler, fail. */
- return NULL;
- #endif
- alias_node = varpool_node::create_alias (alias, decl);
- alias_node->cpp_implicit_alias = true;
- /* Extra name alias mechanizm creates aliases really late
- via DECL_ASSEMBLER_NAME mechanizm.
- This is unfortunate because they are not going through the
- standard channels. Ensure they get output. */
- if (symtab->cpp_implicit_aliases_done)
- alias_node->resolve_alias (varpool_node::get_create (decl));
- return alias_node;
- }
- /* Worker for call_for_symbol_and_aliases. */
- bool
- varpool_node::call_for_symbol_and_aliases_1 (bool (*callback) (varpool_node *,
- void *),
- void *data,
- bool include_overwritable)
- {
- ipa_ref *ref;
- FOR_EACH_ALIAS (this, ref)
- {
- varpool_node *alias = dyn_cast <varpool_node *> (ref->referring);
- if (include_overwritable
- || alias->get_availability () > AVAIL_INTERPOSABLE)
- if (alias->call_for_symbol_and_aliases (callback, data,
- include_overwritable))
- return true;
- }
- return false;
- }
|