Mercurial > hg > CbC > CbC_gcc
diff gcc/varpool.c @ 67:f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
author | nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 22 Mar 2011 17:18:12 +0900 |
parents | b7f97abdc517 |
children | 04ced10e8804 |
line wrap: on
line diff
--- a/gcc/varpool.c Tue May 25 18:58:51 2010 +0900 +++ b/gcc/varpool.c Tue Mar 22 17:18:12 2011 +0900 @@ -1,5 +1,5 @@ /* Callgraph handling code. - Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2010 + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011 Free Software Foundation, Inc. Contributed by Jan Hubicka @@ -26,7 +26,7 @@ #include "tree.h" #include "cgraph.h" #include "langhooks.h" -#include "diagnostic.h" +#include "diagnostic-core.h" #include "hashtab.h" #include "ggc.h" #include "timevar.h" @@ -107,17 +107,20 @@ /* Return varpool node assigned to DECL without creating new one. */ struct varpool_node * -varpool_get_node (tree decl) +varpool_get_node (const_tree decl) { struct varpool_node key, **slot; - gcc_assert (DECL_P (decl) && TREE_CODE (decl) != FUNCTION_DECL); + gcc_assert (TREE_CODE (decl) == VAR_DECL + && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))); if (!varpool_hash) return NULL; - key.decl = decl; + key.decl = CONST_CAST2 (tree, const_tree, decl); slot = (struct varpool_node **) - htab_find_slot (varpool_hash, &key, INSERT); + htab_find_slot (varpool_hash, &key, NO_INSERT); + if (!slot) + return NULL; return *slot; } @@ -127,7 +130,8 @@ { struct varpool_node key, *node, **slot; - gcc_assert (DECL_P (decl) && TREE_CODE (decl) != FUNCTION_DECL); + gcc_assert (TREE_CODE (decl) == VAR_DECL + && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))); if (!varpool_hash) varpool_hash = htab_create_ggc (10, hash_varpool_node, @@ -137,7 +141,7 @@ htab_find_slot (varpool_hash, &key, INSERT); if (*slot) return *slot; - node = GGC_CNEW (struct varpool_node); + node = ggc_alloc_cleared_varpool_node (); node->decl = decl; node->order = cgraph_order++; node->next = varpool_nodes; @@ -237,6 +241,9 @@ fprintf (f, " output"); if (node->externally_visible) fprintf (f, " externally_visible"); + if (node->resolution != LDPR_UNKNOWN) + fprintf (f, " %s", + ld_plugin_symbol_resolution_names[(int)node->resolution]); if (node->in_other_partition) fprintf (f, " in_other_partition"); else if (node->used_from_other_partition) @@ -261,7 +268,7 @@ /* Dump the variable pool to stderr. */ -void +DEBUG_FUNCTION void debug_varpool (void) { dump_varpool (stderr); @@ -327,42 +334,64 @@ bool decide_is_variable_needed (struct varpool_node *node, tree decl) { - if (node->used_from_other_partition) + /* If the user told us it is used, then it must be so. */ + if (node->force_output) return true; - /* If the user told us it is used, then it must be so. */ - if ((node->externally_visible && !DECL_COMDAT (decl)) - || node->force_output) - return true; + + gcc_assert (!DECL_EXTERNAL (decl)); /* Externally visible variables must be output. The exception is COMDAT variables that must be output only when they are needed. */ if (TREE_PUBLIC (decl) - && !flag_whole_program - && !flag_lto - && !flag_whopr && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl)) return true; - /* When emulating tls, we actually see references to the control - variable, rather than the user-level variable. */ - if (!targetm.have_tls - && TREE_CODE (decl) == VAR_DECL - && DECL_THREAD_LOCAL_P (decl)) - { - tree control = emutls_decl (decl); - if (decide_is_variable_needed (varpool_node (control), control)) - return true; - } - /* When not reordering top level variables, we have to assume that we are going to keep everything. */ - if (flag_toplevel_reorder) + if (!flag_toplevel_reorder) + return true; + return false; +} + +/* Return if DECL is constant and its initial value is known (so we can do + constant folding using DECL_INITIAL (decl)). */ + +bool +const_value_known_p (tree decl) +{ + if (TREE_CODE (decl) != VAR_DECL + &&TREE_CODE (decl) != CONST_DECL) return false; - /* We want to emit COMDAT variables only when absolutely necessary. */ - if (DECL_COMDAT (decl)) + if (TREE_CODE (decl) == CONST_DECL + || DECL_IN_CONSTANT_POOL (decl)) + return true; + + gcc_assert (TREE_CODE (decl) == VAR_DECL); + + if (!TREE_READONLY (decl) || TREE_THIS_VOLATILE (decl)) return false; + + /* Gimplifier takes away constructors of local vars */ + if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl)) + return DECL_INITIAL (decl) != NULL; + + gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl)); + + /* Variables declared 'const' without an initializer + have zero as the initializer if they may not be + overridden at link or run time. */ + if (!DECL_INITIAL (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; } @@ -374,6 +403,8 @@ { struct varpool_node *node = varpool_node (decl); + gcc_assert (TREE_STATIC (decl)); + /* The first declaration of a variable that comes through this function decides whether it is global (in C, has external linkage) or local (in C, has internal linkage). So do nothing more @@ -392,11 +423,6 @@ if (decide_is_variable_needed (node, decl)) varpool_mark_needed_node (node); - /* Since we reclaim unreachable nodes at the end of every language - level unit, we need to be conservative about possible entry points - there. */ - else if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl)) - varpool_mark_needed_node (node); if (cgraph_global_info_ready) varpool_assemble_pending_decls (); } @@ -414,7 +440,7 @@ /* If the variable can be overwritten, return OVERWRITABLE. Takes care of at least two notable extensions - the COMDAT variables used to share template instantiations in C++. */ - if (!(*targetm.binds_local_p) (node->decl) && !DECL_COMDAT (node->decl)) + if (!decl_replaceable_p (node->decl)) return AVAIL_OVERWRITABLE; return AVAIL_AVAILABLE; } @@ -517,23 +543,19 @@ varpool_reset_queue (); - if (errorcount || sorrycount) + if (seen_error ()) return; while (node) { - tree decl = node->decl; next = node->next_needed; node->needed = 0; - if (node->finalized - && (decide_is_variable_needed (node, decl) - /* ??? Cgraph does not yet rule the world with an iron hand, - and does not control the emission of debug information. - After a variable has its DECL_RTL set, we must assume that - it may be referenced by the debug information, and we can - no longer elide it. */ - || DECL_RTL_SET_P (decl))) + if (node->analyzed + && (!varpool_can_remove_if_no_refs (node) + /* We just expanded all function bodies. See if any of + them needed the variable. */ + || DECL_RTL_SET_P (node->decl))) varpool_mark_needed_node (node); node = next; @@ -543,13 +565,31 @@ varpool_analyze_pending_decls (); } +/* 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_finalize_named_section_flags (struct varpool_node *node) +{ + if (!TREE_ASM_WRITTEN (node->decl) + && !node->alias + && !node->in_other_partition + && !DECL_EXTERNAL (node->decl) + && TREE_CODE (node->decl) == VAR_DECL + && !DECL_HAS_VALUE_EXPR_P (node->decl) + && DECL_SECTION_NAME (node->decl)) + get_variable_section (node->decl, false); +} + /* Output all variables enqueued to be assembled. */ bool varpool_assemble_pending_decls (void) { bool changed = false; + struct varpool_node *node; - if (errorcount || sorrycount) + if (seen_error ()) return false; timevar_push (TV_VAROUT); @@ -558,6 +598,9 @@ elsewhere. */ varpool_analyze_pending_decls (); + for (node = varpool_nodes_queue; node; node = node->next_needed) + varpool_finalize_named_section_flags (node); + while (varpool_nodes_queue) { struct varpool_node *node = varpool_nodes_queue; @@ -626,7 +669,7 @@ /* Attempt to mark ALIAS as an alias to DECL. Return TRUE if successful. Extra name aliases are output whenever DECL is output. */ -bool +struct varpool_node * varpool_extra_name_alias (tree alias, tree decl) { struct varpool_node key, *alias_node, *decl_node, **slot; @@ -647,9 +690,9 @@ /* If the varpool_node has been already created, fail. */ if (*slot) - return false; + return NULL; - alias_node = GGC_CNEW (struct varpool_node); + alias_node = ggc_alloc_cleared_varpool_node (); alias_node->decl = alias; alias_node->alias = 1; alias_node->extra_name = decl_node; @@ -659,7 +702,26 @@ decl_node->extra_name->prev = alias_node; decl_node->extra_name = alias_node; *slot = alias_node; - return true; + return alias_node; +} + +/* Return true when NODE is known to be used from other (non-LTO) object file. + Known only when doing LTO via linker plugin. */ + +bool +varpool_used_from_object_file_p (struct varpool_node *node) +{ + struct varpool_node *alias; + + if (!TREE_PUBLIC (node->decl)) + return false; + if (resolution_used_from_other_file_p (node->resolution)) + return true; + for (alias = node->extra_name; alias; alias = alias->next) + if (TREE_PUBLIC (alias->decl) + && resolution_used_from_other_file_p (alias->resolution)) + return true; + return false; } #include "gt-varpool.h"