Mercurial > hg > CbC > CbC_gcc
diff gcc/varpool.c @ 63:b7f97abdc517 gcc-4.6-20100522
update gcc from gcc-4.5.0 to gcc-4.6
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 24 May 2010 12:47:05 +0900 |
parents | 77e2b8dfacca |
children | f6334be47118 |
line wrap: on
line diff
--- a/gcc/varpool.c Fri Feb 12 23:41:23 2010 +0900 +++ b/gcc/varpool.c Mon May 24 12:47:05 2010 +0900 @@ -1,5 +1,5 @@ /* Callgraph handling code. - Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2010 Free Software Foundation, Inc. Contributed by Jan Hubicka @@ -105,6 +105,22 @@ return DECL_UID (n1->decl) == DECL_UID (n2->decl); } +/* Return varpool node assigned to DECL without creating new one. */ +struct varpool_node * +varpool_get_node (tree decl) +{ + struct varpool_node key, **slot; + + gcc_assert (DECL_P (decl) && TREE_CODE (decl) != FUNCTION_DECL); + + if (!varpool_hash) + return NULL; + key.decl = decl; + slot = (struct varpool_node **) + htab_find_slot (varpool_hash, &key, INSERT); + return *slot; +} + /* Return varpool node assigned to DECL. Create new one when needed. */ struct varpool_node * varpool_node (tree decl) @@ -125,11 +141,77 @@ node->decl = decl; node->order = cgraph_order++; node->next = varpool_nodes; + ipa_empty_ref_list (&node->ref_list); + if (varpool_nodes) + varpool_nodes->prev = node; varpool_nodes = node; *slot = node; return node; } +/* Remove node from the varpool. */ +void +varpool_remove_node (struct varpool_node *node) +{ + void **slot; + slot = htab_find_slot (varpool_hash, node, NO_INSERT); + gcc_assert (*slot == node); + htab_clear_slot (varpool_hash, slot); + gcc_assert (!varpool_assembled_nodes_queue); + if (!node->alias) + while (node->extra_name) + varpool_remove_node (node->extra_name); + if (node->next) + node->next->prev = node->prev; + if (node->prev) + node->prev->next = node->next; + else + { + if (node->alias && node->extra_name) + { + gcc_assert (node->extra_name->extra_name == node); + node->extra_name->extra_name = node->next; + } + else + { + gcc_assert (varpool_nodes == node); + varpool_nodes = node->next; + } + } + if (varpool_first_unanalyzed_node == node) + varpool_first_unanalyzed_node = node->next_needed; + if (node->next_needed) + node->next_needed->prev_needed = node->prev_needed; + else if (node->prev_needed) + { + gcc_assert (varpool_last_needed_node); + varpool_last_needed_node = node->prev_needed; + } + if (node->prev_needed) + node->prev_needed->next_needed = node->next_needed; + else if (node->next_needed) + { + gcc_assert (varpool_nodes_queue == node); + varpool_nodes_queue = node->next_needed; + } + if (node->same_comdat_group) + { + struct varpool_node *prev; + for (prev = node->same_comdat_group; + prev->same_comdat_group != node; + prev = prev->same_comdat_group) + ; + if (node->same_comdat_group == prev) + prev->same_comdat_group = NULL; + else + prev->same_comdat_group = node->same_comdat_group; + node->same_comdat_group = NULL; + } + ipa_remove_all_references (&node->ref_list); + ipa_remove_all_refering (&node->ref_list); + ggc_free (node); +} + /* Dump given cgraph node. */ void dump_varpool_node (FILE *f, struct varpool_node *node) @@ -139,8 +221,12 @@ cgraph_function_flags_ready ? cgraph_availability_names[cgraph_variable_initializer_availability (node)] : "not-ready"); + if (DECL_ASSEMBLER_NAME_SET_P (node->decl)) + fprintf (f, " (asm: %s)", IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl))); if (DECL_INITIAL (node->decl)) fprintf (f, " initialized"); + if (TREE_ASM_WRITTEN (node->decl)) + fprintf (f, " (asm written)"); if (node->needed) fprintf (f, " needed"); if (node->analyzed) @@ -151,7 +237,15 @@ fprintf (f, " output"); if (node->externally_visible) fprintf (f, " externally_visible"); + if (node->in_other_partition) + fprintf (f, " in_other_partition"); + else if (node->used_from_other_partition) + fprintf (f, " used_from_other_partition"); fprintf (f, "\n"); + fprintf (f, " References: "); + ipa_dump_references (f, &node->ref_list); + fprintf (f, " Refering this var: "); + ipa_dump_refering (f, &node->ref_list); } /* Dump the variable pool. */ @@ -192,7 +286,10 @@ varpool_enqueue_needed_node (struct varpool_node *node) { if (varpool_last_needed_node) - varpool_last_needed_node->next_needed = node; + { + varpool_last_needed_node->next_needed = node; + node->prev_needed = varpool_last_needed_node; + } varpool_last_needed_node = node; node->next_needed = NULL; if (!varpool_nodes_queue) @@ -207,6 +304,8 @@ void varpool_mark_needed_node (struct varpool_node *node) { + if (node->alias && node->extra_name) + node = node->extra_name; if (!node->needed && node->finalized && !TREE_ASM_WRITTEN (node->decl)) varpool_enqueue_needed_node (node); @@ -214,7 +313,7 @@ } /* Reset the queue of needed nodes. */ -static void +void varpool_reset_queue (void) { varpool_last_needed_node = NULL; @@ -228,18 +327,13 @@ bool decide_is_variable_needed (struct varpool_node *node, tree decl) { + if (node->used_from_other_partition) + 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; - /* ??? If the assembler name is set by hand, it is possible to assemble - the name later after finalizing the function and the fact is noticed - in assemble_name then. This is arguably a bug. */ - if (DECL_ASSEMBLER_NAME_SET_P (decl) - && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))) - return true; - /* Externally visible variables must be output. The exception is COMDAT variables that must be output only when they are needed. */ if (TREE_PUBLIC (decl) @@ -280,17 +374,6 @@ { struct varpool_node *node = varpool_node (decl); - /* FIXME: We don't really stream varpool datastructure and instead rebuild it - by varpool_finalize_decl. This is not quite correct since this way we can't - attach any info to varpool. Eventually we will want to stream varpool nodes - and the flags. - - For the moment just prevent analysis of varpool nodes to happen again, so - we will re-try to compute "address_taken" flag of varpool that breaks - in presence of clones. */ - if (in_lto_p) - node->analyzed = true; - /* 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 @@ -304,6 +387,8 @@ if (node->needed) varpool_enqueue_needed_node (node); node->finalized = true; + if (TREE_THIS_VOLATILE (decl) || DECL_PRESERVE_P (decl)) + node->force_output = true; if (decide_is_variable_needed (node, decl)) varpool_mark_needed_node (node); @@ -340,12 +425,13 @@ varpool_analyze_pending_decls (void) { bool changed = false; - timevar_push (TV_CGRAPH); + timevar_push (TV_VARPOOL); while (varpool_first_unanalyzed_node) { - tree decl = varpool_first_unanalyzed_node->decl; - bool analyzed = varpool_first_unanalyzed_node->analyzed; + struct varpool_node *node = varpool_first_unanalyzed_node, *next; + tree decl = node->decl; + bool analyzed = node->analyzed; varpool_first_unanalyzed_node->analyzed = true; @@ -356,16 +442,23 @@ We however don't want to re-analyze already analyzed nodes. */ if (!analyzed) { - gcc_assert (!in_lto_p); + gcc_assert (!in_lto_p || cgraph_function_flags_ready); /* Compute the alignment early so function body expanders are already informed about increased alignment. */ align_variable (decl, 0); } if (DECL_INITIAL (decl)) record_references_in_initializer (decl, analyzed); + if (node->same_comdat_group) + { + for (next = node->same_comdat_group; + next != node; + next = next->same_comdat_group) + varpool_mark_needed_node (next); + } changed = true; } - timevar_pop (TV_CGRAPH); + timevar_pop (TV_VARPOOL); return changed; } @@ -377,15 +470,32 @@ if (!TREE_ASM_WRITTEN (decl) && !node->alias + && !node->in_other_partition && !DECL_EXTERNAL (decl) && (TREE_CODE (decl) != VAR_DECL || !DECL_HAS_VALUE_EXPR_P (decl))) { assemble_variable (decl, 0, 1, 0); if (TREE_ASM_WRITTEN (decl)) { + struct varpool_node *alias; + node->next_needed = varpool_assembled_nodes_queue; + node->prev_needed = NULL; + if (varpool_assembled_nodes_queue) + varpool_assembled_nodes_queue->prev_needed = node; varpool_assembled_nodes_queue = node; node->finalized = 1; + + /* Also emit any extra name aliases. */ + for (alias = node->extra_name; alias; alias = alias->next) + { + /* Update linkage fields in case they've changed. */ + DECL_WEAK (alias->decl) = DECL_WEAK (decl); + TREE_PUBLIC (alias->decl) = TREE_PUBLIC (decl); + DECL_VISIBILITY (alias->decl) = DECL_VISIBILITY (decl); + assemble_alias (alias->decl, DECL_ASSEMBLER_NAME (decl)); + } + return true; } } @@ -442,6 +552,7 @@ if (errorcount || sorrycount) return false; + timevar_push (TV_VAROUT); /* EH might mark decls as needed during expansion. This should be safe since we don't create references to new function, but it should not be used elsewhere. */ @@ -455,11 +566,15 @@ if (varpool_assemble_decl (node)) changed = true; else - node->next_needed = NULL; + { + node->prev_needed = NULL; + node->next_needed = NULL; + } } /* varpool_nodes_queue is now empty, clear the pointer to the last element in the queue. */ varpool_last_needed_node = NULL; + timevar_pop (TV_VAROUT); return changed; } @@ -477,6 +592,7 @@ struct varpool_node *node = varpool_nodes_queue; varpool_nodes_queue = varpool_nodes_queue->next_needed; node->next_needed = NULL; + node->prev_needed = NULL; } /* varpool_nodes_queue is now empty, clear the pointer to the last element in the queue. */ @@ -507,4 +623,43 @@ return new_node->decl; } +/* Attempt to mark ALIAS as an alias to DECL. Return TRUE if successful. + Extra name aliases are output whenever DECL is output. */ + +bool +varpool_extra_name_alias (tree alias, tree decl) +{ + struct varpool_node key, *alias_node, *decl_node, **slot; + +#ifndef ASM_OUTPUT_DEF + /* If aliases aren't supported by the assembler, fail. */ + return false; +#endif + + gcc_assert (TREE_CODE (decl) == VAR_DECL); + gcc_assert (TREE_CODE (alias) == VAR_DECL); + /* Make sure the hash table has been created. */ + decl_node = varpool_node (decl); + + key.decl = alias; + + slot = (struct varpool_node **) htab_find_slot (varpool_hash, &key, INSERT); + + /* If the varpool_node has been already created, fail. */ + if (*slot) + return false; + + alias_node = GGC_CNEW (struct varpool_node); + alias_node->decl = alias; + alias_node->alias = 1; + alias_node->extra_name = decl_node; + alias_node->next = decl_node->extra_name; + ipa_empty_ref_list (&alias_node->ref_list); + if (decl_node->extra_name) + decl_node->extra_name->prev = alias_node; + decl_node->extra_name = alias_node; + *slot = alias_node; + return true; +} + #include "gt-varpool.h"