cgraph.c (cgraph_hash, [...]): Remove.

* cgraph.c (cgraph_hash, assembler_name_hash): Remove.
	(hash_node, eq_node): Remove.
	(cgraph_create_node): Do not handle hashtable.
	(cgraph_get_node): Remove.
	(cgraph_insert_node_to_hashtable): Remove.
	(hash_node_by_assembler_name): Remove.
	(eq_assembler_name): Remove.
	(cgraph_node_for_asm): Rewrite.
	(cgraph_find_replacement_node): Break out from ...
	(cgraph_remove_node): ... here; do not maintain hashtables.
	(change_decl_assembler_name): Remove.
	(cgraph_clone_node): Do not maintain hashtables.
	* cgraph.h (const_symtab_node): New typedef.
	(cgraph_insert_node_to_hashtable): Remove.
	(symtab_get_node, symtab_node_for_asm,
	symtab_insert_node_to_hashtable): Declare.
	(cgraph_find_replacement_node): Declare.
	(cgraph_get_node, varpool_get_node): Turn into inlines.
	(cgraph, varpool): Work sanely on NULL pointers.
	(FOR_EACH_SYMBOL): New walker.
	* ipa-inline-transform.c (save_inline_function_body): Use
	symtab_insert_node_to_hashtable.
	* symtab.c: Include ggc.h and diagnostics.h
	(symtab_hash, assembler_name_hash): New static vars;
	(hash_node, eq_node, hash_node_by_assembler_name,
	eq_assembler_name, insert_to_assembler_name_hash,
	unlink_from_assembler_name_hash): New.
	(symtab_register_node): Update hashtables.
	(symtab_insert_node_to_hashtable): New.
	(symtab_unregister_node): Update hashtables.
	(symtab_get_node): New.
	(symtab_node_for_asm): New.
	(change_decl_assembler_name): New.
	* Makefile.in (symtab.o): Needs GTY.
	* varpool.c (varpool_hash): Remove.
	(hash_varpool_node, eq_varpool_node, varpool_get_node): Remove.
	(varpool_node): Rewrite using varpool_get_node.
	(varpool_remove_node): DO not maintain hashtables.
	(varpool_node_for_asm); Rewrite.

From-SVN: r186525
This commit is contained in:
Jan Hubicka 2012-04-17 12:53:22 +02:00 committed by Jan Hubicka
parent 332781bba5
commit 1ab24192d5
7 changed files with 420 additions and 379 deletions

View File

@ -1,3 +1,45 @@
2012-04-16 Jan Hubicka <jh@suse.cz>
* cgraph.c (cgraph_hash, assembler_name_hash): Remove.
(hash_node, eq_node): Remove.
(cgraph_create_node): Do not handle hashtable.
(cgraph_get_node): Remove.
(cgraph_insert_node_to_hashtable): Remove.
(hash_node_by_assembler_name): Remove.
(eq_assembler_name): Remove.
(cgraph_node_for_asm): Rewrite.
(cgraph_find_replacement_node): Break out from ...
(cgraph_remove_node): ... here; do not maintain hashtables.
(change_decl_assembler_name): Remove.
(cgraph_clone_node): Do not maintain hashtables.
* cgraph.h (const_symtab_node): New typedef.
(cgraph_insert_node_to_hashtable): Remove.
(symtab_get_node, symtab_node_for_asm,
symtab_insert_node_to_hashtable): Declare.
(cgraph_find_replacement_node): Declare.
(cgraph_get_node, varpool_get_node): Turn into inlines.
(cgraph, varpool): Work sanely on NULL pointers.
(FOR_EACH_SYMBOL): New walker.
* ipa-inline-transform.c (save_inline_function_body): Use
symtab_insert_node_to_hashtable.
* symtab.c: Include ggc.h and diagnostics.h
(symtab_hash, assembler_name_hash): New static vars;
(hash_node, eq_node, hash_node_by_assembler_name,
eq_assembler_name, insert_to_assembler_name_hash,
unlink_from_assembler_name_hash): New.
(symtab_register_node): Update hashtables.
(symtab_insert_node_to_hashtable): New.
(symtab_unregister_node): Update hashtables.
(symtab_get_node): New.
(symtab_node_for_asm): New.
(change_decl_assembler_name): New.
* Makefile.in (symtab.o): Needs GTY.
* varpool.c (varpool_hash): Remove.
(hash_varpool_node, eq_varpool_node, varpool_get_node): Remove.
(varpool_node): Rewrite using varpool_get_node.
(varpool_remove_node): DO not maintain hashtables.
(varpool_node_for_asm); Rewrite.
2012-04-16 Sandra Loosemore <sandra@codesourcery.com>
* doc/invoke.texi: Copy-edit to put verbs in the present tense

View File

@ -2912,7 +2912,7 @@ simplify-rtx.o : simplify-rtx.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) $(TARGET_H)
symtab.o : symtab.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
langhooks.h toplev.h $(DIAGNOSTIC_CORE_H) $(FLAGS_H) $(GGC_H) $(TARGET_H) $(CGRAPH_H) \
$(HASHTAB_H)
$(HASHTAB_H) gt-symtab.h
cgraph.o : cgraph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
langhooks.h toplev.h $(DIAGNOSTIC_CORE_H) $(FLAGS_H) $(GGC_H) $(TARGET_H) $(CGRAPH_H) \
gt-cgraph.h output.h intl.h $(BASIC_BLOCK_H) debug.h $(HASHTAB_H) \
@ -3690,7 +3690,7 @@ GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
$(srcdir)/fixed-value.h \
$(srcdir)/output.h $(srcdir)/cfgloop.h \
$(srcdir)/cselib.h $(srcdir)/basic-block.h $(srcdir)/ipa-ref.h $(srcdir)/cgraph.h \
$(srcdir)/reload.h $(srcdir)/caller-save.c \
$(srcdir)/reload.h $(srcdir)/caller-save.c $(srcdir)/symtab.c \
$(srcdir)/alias.c $(srcdir)/bitmap.c $(srcdir)/cselib.c $(srcdir)/cgraph.c \
$(srcdir)/ipa-prop.c $(srcdir)/ipa-cp.c $(srcdir)/matrix-reorg.c \
$(srcdir)/dbxout.c \

View File

@ -119,11 +119,6 @@ static void cgraph_node_remove_callers (struct cgraph_node *node);
static inline void cgraph_edge_remove_caller (struct cgraph_edge *e);
static inline void cgraph_edge_remove_callee (struct cgraph_edge *e);
/* Hash table used to convert declarations into nodes. */
static GTY((param_is (union symtab_node_def))) htab_t cgraph_hash;
/* Hash table used to convert assembler names into nodes. */
static GTY((param_is (union symtab_node_def))) htab_t assembler_name_hash;
/* Queue of cgraph nodes scheduled to be lowered. */
symtab_node x_cgraph_nodes_queue;
#define cgraph_nodes_queue ((struct cgraph_node *)x_cgraph_nodes_queue)
@ -419,26 +414,6 @@ cgraph_call_node_duplication_hooks (struct cgraph_node *node1,
}
}
/* Returns a hash code for P. */
static hashval_t
hash_node (const void *p)
{
const struct cgraph_node *n = (const struct cgraph_node *) p;
return (hashval_t) DECL_UID (n->symbol.decl);
}
/* Returns nonzero if P1 and P2 are equal. */
static int
eq_node (const void *p1, const void *p2)
{
const struct cgraph_node *n1 = (const struct cgraph_node *) p1;
const struct cgraph_node *n2 = (const struct cgraph_node *) p2;
return DECL_UID (n1->symbol.decl) == DECL_UID (n2->symbol.decl);
}
/* Allocate new callgraph node. */
static inline struct cgraph_node *
@ -479,42 +454,18 @@ cgraph_create_node_1 (void)
struct cgraph_node *
cgraph_create_node (tree decl)
{
struct cgraph_node key, *node, **slot;
struct cgraph_node *node = cgraph_create_node_1 ();
gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
if (!cgraph_hash)
cgraph_hash = htab_create_ggc (10, hash_node, eq_node, NULL);
key.symbol.decl = decl;
slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, &key, INSERT);
gcc_assert (!*slot);
node = cgraph_create_node_1 ();
node->symbol.decl = decl;
symtab_register_node ((symtab_node)node);
*slot = node;
symtab_register_node ((symtab_node) node);
if (DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)
{
node->origin = cgraph_get_create_node (DECL_CONTEXT (decl));
node->next_nested = node->origin->nested;
node->origin->nested = node;
}
if (assembler_name_hash)
{
void **aslot;
tree name = DECL_ASSEMBLER_NAME (decl);
aslot = htab_find_slot_with_hash (assembler_name_hash, name,
decl_assembler_name_hash (name),
INSERT);
/* We can have multiple declarations with same assembler name. For C++
it is __builtin_strlen and strlen, for instance. Do we need to
record them all? Original implementation marked just first one
so lets hope for the best. */
if (*aslot == NULL)
*aslot = node;
}
return node;
}
@ -629,100 +580,18 @@ cgraph_add_thunk (struct cgraph_node *decl_node ATTRIBUTE_UNUSED,
return node;
}
/* Returns the cgraph node assigned to DECL or NULL if no cgraph node
is assigned. */
struct cgraph_node *
cgraph_get_node (const_tree decl)
{
struct cgraph_node key, *node = NULL, **slot;
gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
if (!cgraph_hash)
return NULL;
key.symbol.decl = CONST_CAST2 (tree, const_tree, decl);
slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, &key,
NO_INSERT);
if (slot && *slot)
node = *slot;
return node;
}
/* Insert already constructed node into hashtable. */
void
cgraph_insert_node_to_hashtable (struct cgraph_node *node)
{
struct cgraph_node **slot;
slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, node, INSERT);
gcc_assert (!*slot);
*slot = node;
}
/* Returns a hash code for P. */
static hashval_t
hash_node_by_assembler_name (const void *p)
{
const struct cgraph_node *n = (const struct cgraph_node *) p;
return (hashval_t) decl_assembler_name_hash (DECL_ASSEMBLER_NAME (n->symbol.decl));
}
/* Returns nonzero if P1 and P2 are equal. */
static int
eq_assembler_name (const void *p1, const void *p2)
{
const struct cgraph_node *n1 = (const struct cgraph_node *) p1;
const_tree name = (const_tree)p2;
return (decl_assembler_name_equal (n1->symbol.decl, name));
}
/* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME.
Return NULL if there's no such node. */
struct cgraph_node *
cgraph_node_for_asm (tree asmname)
{
struct cgraph_node *node;
void **slot;
symtab_node node = symtab_node_for_asm (asmname);
if (!assembler_name_hash)
{
assembler_name_hash =
htab_create_ggc (10, hash_node_by_assembler_name, eq_assembler_name,
NULL);
FOR_EACH_FUNCTION (node)
if (!node->global.inlined_to)
{
tree name = DECL_ASSEMBLER_NAME (node->symbol.decl);
slot = htab_find_slot_with_hash (assembler_name_hash, name,
decl_assembler_name_hash (name),
INSERT);
/* We can have multiple declarations with same assembler name. For C++
it is __builtin_strlen and strlen, for instance. Do we need to
record them all? Original implementation marked just first one
so lets hope for the best. */
if (!*slot)
*slot = node;
}
}
slot = htab_find_slot_with_hash (assembler_name_hash, asmname,
decl_assembler_name_hash (asmname),
NO_INSERT);
if (slot)
{
node = (struct cgraph_node *) *slot;
return node;
}
/* We do not want to look at inline clones. */
for (node = symtab_node_for_asm (asmname); node; node = node->symbol.next_sharing_asm_name)
if (symtab_function_p (node) && !cgraph(node)->global.inlined_to)
return cgraph (node);
return NULL;
}
@ -1392,13 +1261,96 @@ cgraph_release_function_body (struct cgraph_node *node)
DECL_INITIAL (node->symbol.decl) = error_mark_node;
}
/* NODE is being removed from symbol table; see if its entry can be replaced by
other inline clone. */
struct cgraph_node *
cgraph_find_replacement_node (struct cgraph_node *node)
{
struct cgraph_node *next_inline_clone, *replacement;
for (next_inline_clone = node->clones;
next_inline_clone
&& next_inline_clone->symbol.decl != node->symbol.decl;
next_inline_clone = next_inline_clone->next_sibling_clone)
;
/* If there is inline clone of the node being removed, we need
to put it into the position of removed node and reorganize all
other clones to be based on it. */
if (next_inline_clone)
{
struct cgraph_node *n;
struct cgraph_node *new_clones;
replacement = next_inline_clone;
/* Unlink inline clone from the list of clones of removed node. */
if (next_inline_clone->next_sibling_clone)
next_inline_clone->next_sibling_clone->prev_sibling_clone
= next_inline_clone->prev_sibling_clone;
if (next_inline_clone->prev_sibling_clone)
{
gcc_assert (node->clones != next_inline_clone);
next_inline_clone->prev_sibling_clone->next_sibling_clone
= next_inline_clone->next_sibling_clone;
}
else
{
gcc_assert (node->clones == next_inline_clone);
node->clones = next_inline_clone->next_sibling_clone;
}
new_clones = node->clones;
node->clones = NULL;
/* Copy clone info. */
next_inline_clone->clone = node->clone;
/* Now place it into clone tree at same level at NODE. */
next_inline_clone->clone_of = node->clone_of;
next_inline_clone->prev_sibling_clone = NULL;
next_inline_clone->next_sibling_clone = NULL;
if (node->clone_of)
{
if (node->clone_of->clones)
node->clone_of->clones->prev_sibling_clone = next_inline_clone;
next_inline_clone->next_sibling_clone = node->clone_of->clones;
node->clone_of->clones = next_inline_clone;
}
/* Merge the clone list. */
if (new_clones)
{
if (!next_inline_clone->clones)
next_inline_clone->clones = new_clones;
else
{
n = next_inline_clone->clones;
while (n->next_sibling_clone)
n = n->next_sibling_clone;
n->next_sibling_clone = new_clones;
new_clones->prev_sibling_clone = n;
}
}
/* Update clone_of pointers. */
n = new_clones;
while (n)
{
n->clone_of = next_inline_clone;
n = n->next_sibling_clone;
}
return replacement;
}
else
return NULL;
}
/* Remove the node from cgraph. */
void
cgraph_remove_node (struct cgraph_node *node)
{
void **slot;
bool kill_body = false;
struct cgraph_node *n;
int uid = node->uid;
@ -1423,91 +1375,6 @@ cgraph_remove_node (struct cgraph_node *node)
*node2 = node->next_nested;
}
symtab_unregister_node ((symtab_node)node);
slot = htab_find_slot (cgraph_hash, node, NO_INSERT);
if (*slot == node)
{
struct cgraph_node *next_inline_clone;
for (next_inline_clone = node->clones;
next_inline_clone
&& next_inline_clone->symbol.decl != node->symbol.decl;
next_inline_clone = next_inline_clone->next_sibling_clone)
;
/* If there is inline clone of the node being removed, we need
to put it into the position of removed node and reorganize all
other clones to be based on it. */
if (next_inline_clone)
{
struct cgraph_node *n;
struct cgraph_node *new_clones;
*slot = next_inline_clone;
/* Unlink inline clone from the list of clones of removed node. */
if (next_inline_clone->next_sibling_clone)
next_inline_clone->next_sibling_clone->prev_sibling_clone
= next_inline_clone->prev_sibling_clone;
if (next_inline_clone->prev_sibling_clone)
{
gcc_assert (node->clones != next_inline_clone);
next_inline_clone->prev_sibling_clone->next_sibling_clone
= next_inline_clone->next_sibling_clone;
}
else
{
gcc_assert (node->clones == next_inline_clone);
node->clones = next_inline_clone->next_sibling_clone;
}
new_clones = node->clones;
node->clones = NULL;
/* Copy clone info. */
next_inline_clone->clone = node->clone;
/* Now place it into clone tree at same level at NODE. */
next_inline_clone->clone_of = node->clone_of;
next_inline_clone->prev_sibling_clone = NULL;
next_inline_clone->next_sibling_clone = NULL;
if (node->clone_of)
{
if (node->clone_of->clones)
node->clone_of->clones->prev_sibling_clone = next_inline_clone;
next_inline_clone->next_sibling_clone = node->clone_of->clones;
node->clone_of->clones = next_inline_clone;
}
/* Merge the clone list. */
if (new_clones)
{
if (!next_inline_clone->clones)
next_inline_clone->clones = new_clones;
else
{
n = next_inline_clone->clones;
while (n->next_sibling_clone)
n = n->next_sibling_clone;
n->next_sibling_clone = new_clones;
new_clones->prev_sibling_clone = n;
}
}
/* Update clone_of pointers. */
n = new_clones;
while (n)
{
n->clone_of = next_inline_clone;
n = n->next_sibling_clone;
}
}
else
{
htab_clear_slot (cgraph_hash, slot);
kill_body = true;
}
}
if (node->prev_sibling_clone)
node->prev_sibling_clone->next_sibling_clone = node->next_sibling_clone;
else if (node->clone_of)
@ -1549,29 +1416,15 @@ cgraph_remove_node (struct cgraph_node *node)
itself is kept in the cgraph even after it is compiled. Check whether
we are done with this body and reclaim it proactively if this is the case.
*/
if (!kill_body && *slot)
{
struct cgraph_node *n = (struct cgraph_node *) *slot;
if (!n->clones && !n->clone_of && !n->global.inlined_to
n = cgraph_get_node (node->symbol.decl);
if (!n
|| (!n->clones && !n->clone_of && !n->global.inlined_to
&& (cgraph_global_info_ready
&& (TREE_ASM_WRITTEN (n->symbol.decl)
|| DECL_EXTERNAL (n->symbol.decl)
|| n->symbol.in_other_partition)))
kill_body = true;
}
if (assembler_name_hash)
{
tree name = DECL_ASSEMBLER_NAME (node->symbol.decl);
slot = htab_find_slot_with_hash (assembler_name_hash, name,
decl_assembler_name_hash (name),
NO_INSERT);
/* Inline clones are not hashed. */
if (slot && *slot == node)
htab_clear_slot (assembler_name_hash, slot);
}
if (kill_body)
|| n->symbol.in_other_partition))))
cgraph_release_function_body (node);
node->symbol.decl = NULL;
if (node->call_site_hash)
{
@ -1939,51 +1792,6 @@ debug_cgraph (void)
dump_cgraph (stderr);
}
/* Set the DECL_ASSEMBLER_NAME and update cgraph hashtables. */
void
change_decl_assembler_name (tree decl, tree name)
{
struct cgraph_node *node;
void **slot;
if (!DECL_ASSEMBLER_NAME_SET_P (decl))
SET_DECL_ASSEMBLER_NAME (decl, name);
else
{
if (name == DECL_ASSEMBLER_NAME (decl))
return;
if (assembler_name_hash
&& TREE_CODE (decl) == FUNCTION_DECL
&& (node = cgraph_get_node (decl)) != NULL)
{
tree old_name = DECL_ASSEMBLER_NAME (decl);
slot = htab_find_slot_with_hash (assembler_name_hash, old_name,
decl_assembler_name_hash (old_name),
NO_INSERT);
/* Inline clones are not hashed. */
if (slot && *slot == node)
htab_clear_slot (assembler_name_hash, slot);
}
if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
&& DECL_RTL_SET_P (decl))
warning (0, "%D renamed after being referenced in assembly", decl);
SET_DECL_ASSEMBLER_NAME (decl, name);
}
if (assembler_name_hash
&& TREE_CODE (decl) == FUNCTION_DECL
&& (node = cgraph_get_node (decl)) != NULL)
{
slot = htab_find_slot_with_hash (assembler_name_hash, name,
decl_assembler_name_hash (name),
INSERT);
gcc_assert (!*slot);
*slot = node;
}
}
/* Add a top-level asm statement to the list. */
struct cgraph_asm_node *
@ -2154,25 +1962,6 @@ cgraph_clone_node (struct cgraph_node *n, tree decl, gcov_type count, int freq,
n->clones = new_node;
new_node->clone_of = n;
if (n->symbol.decl != decl)
{
struct cgraph_node **slot;
slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, new_node, INSERT);
gcc_assert (!*slot);
*slot = new_node;
if (assembler_name_hash)
{
void **aslot;
tree name = DECL_ASSEMBLER_NAME (decl);
aslot = htab_find_slot_with_hash (assembler_name_hash, name,
decl_assembler_name_hash (name),
INSERT);
gcc_assert (!*aslot);
*aslot = new_node;
}
}
if (call_duplication_hook)
cgraph_call_node_duplication_hooks (n, new_node);
return new_node;

View File

@ -40,6 +40,7 @@ enum symtab_type
union symtab_node_def;
typedef union symtab_node_def *symtab_node;
typedef const union symtab_node_def *const_symtab_node;
/* Base of all entries in the symbol table.
The symtab_node is inherited by cgraph and varpol nodes. */
@ -60,6 +61,12 @@ struct GTY(()) symtab_node_base
/* Linked list of symbol table entries starting with symtab_nodes. */
symtab_node next;
symtab_node previous;
/* Linked list of symbols with the same asm name. There may be multiple
entries for single symbol name in the case of LTO resolutions,
existence of inline clones, or duplicated declaration. The last case
is a long standing bug frontends and builtin handling. */
symtab_node next_sharing_asm_name;
symtab_node previous_sharing_asm_name;
PTR GTY ((skip)) aux;
@ -499,15 +506,18 @@ extern bool same_body_aliases_done;
void symtab_register_node (symtab_node);
void symtab_unregister_node (symtab_node);
void symtab_remove_node (symtab_node);
symtab_node symtab_get_node (const_tree);
symtab_node symtab_node_for_asm (const_tree asmname);
void symtab_insert_node_to_hashtable (symtab_node);
/* In cgraph.c */
void dump_cgraph (FILE *);
void debug_cgraph (void);
void dump_cgraph_node (FILE *, struct cgraph_node *);
void debug_cgraph_node (struct cgraph_node *);
void cgraph_insert_node_to_hashtable (struct cgraph_node *node);
void cgraph_remove_edge (struct cgraph_edge *);
void cgraph_remove_node (struct cgraph_node *);
struct cgraph_node *cgraph_find_replacement_node (struct cgraph_node *);
void cgraph_add_to_same_comdat_group (struct cgraph_node *, struct cgraph_node *);
bool cgraph_remove_node_and_inline_clones (struct cgraph_node *, struct cgraph_node *);
void cgraph_release_function_body (struct cgraph_node *);
@ -518,7 +528,6 @@ struct cgraph_edge *cgraph_create_edge (struct cgraph_node *,
struct cgraph_edge *cgraph_create_indirect_edge (struct cgraph_node *, gimple,
int, gcov_type, int);
struct cgraph_indirect_call_info *cgraph_allocate_init_indirect_info (void);
struct cgraph_node * cgraph_get_node (const_tree);
struct cgraph_node * cgraph_create_node (tree);
struct cgraph_node * cgraph_get_create_node (tree);
struct cgraph_node * cgraph_same_body_alias (struct cgraph_node *, tree, tree);
@ -697,7 +706,6 @@ void cgraph_make_node_local (struct cgraph_node *);
bool cgraph_node_can_be_local_p (struct cgraph_node *);
struct varpool_node * varpool_get_node (const_tree decl);
void varpool_remove_node (struct varpool_node *node);
void varpool_finalize_named_section_flags (struct varpool_node *node);
bool varpool_assemble_pending_decls (void);
@ -734,7 +742,7 @@ static inline struct cgraph_node *
cgraph (symtab_node node)
{
gcc_checking_assert (!node || node->symbol.type == SYMTAB_FUNCTION);
return &node->x_function;
return (struct cgraph_node *)node;
}
/* Return varpool node for given symbol and check it is a variable. */
@ -742,9 +750,28 @@ static inline struct varpool_node *
varpool (symtab_node node)
{
gcc_checking_assert (!node || node->symbol.type == SYMTAB_VARIABLE);
return &node->x_variable;
return (struct varpool_node *)node;
}
/* Return callgraph node for given symbol and check it is a function. */
static inline struct cgraph_node *
cgraph_get_node (const_tree decl)
{
gcc_checking_assert (TREE_CODE (decl) == FUNCTION_DECL);
return cgraph (symtab_get_node (decl));
}
/* Return varpool node for given symbol and check it is a function. */
static inline struct varpool_node *
varpool_get_node (const_tree decl)
{
gcc_checking_assert (TREE_CODE (decl) == VAR_DECL);
return varpool (symtab_get_node (decl));
}
/* Walk all symbols. */
#define FOR_EACH_SYMBOL(node) \
for ((node) = symtab_nodes; (node); (node) = (node)->symbol.next)
/* Return first reachable static variable with initializer. */
static inline struct varpool_node *

View File

@ -278,7 +278,7 @@ save_inline_function_body (struct cgraph_node *node)
/* first_clone will be turned into real function. */
first_clone = node->clones;
first_clone->symbol.decl = copy_node (node->symbol.decl);
cgraph_insert_node_to_hashtable (first_clone);
symtab_insert_node_to_hashtable ((symtab_node) first_clone);
gcc_assert (first_clone == cgraph_get_node (first_clone->symbol.decl));
/* Now reshape the clone tree, so all other clones descends from

View File

@ -25,7 +25,14 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "tree-inline.h"
#include "hashtab.h"
#include "ggc.h"
#include "cgraph.h"
#include "diagnostic.h"
/* Hash table used to convert declarations into nodes. */
static GTY((param_is (union symtab_node_def))) htab_t symtab_hash;
/* Hash table used to convert assembler names into nodes. */
static GTY((param_is (union symtab_node_def))) htab_t assembler_name_hash;
/* Linked list of symbol table nodes. */
symtab_node symtab_nodes;
@ -35,29 +42,153 @@ symtab_node symtab_nodes;
them, to support -fno-toplevel-reorder. */
int symtab_order;
/* Returns a hash code for P. */
static hashval_t
hash_node (const void *p)
{
const_symtab_node n = (const_symtab_node ) p;
return (hashval_t) DECL_UID (n->symbol.decl);
}
/* Returns nonzero if P1 and P2 are equal. */
static int
eq_node (const void *p1, const void *p2)
{
const_symtab_node n1 = (const_symtab_node) p1;
const_symtab_node n2 = (const_symtab_node) p2;
return DECL_UID (n1->symbol.decl) == DECL_UID (n2->symbol.decl);
}
/* Returns a hash code for P. */
static hashval_t
hash_node_by_assembler_name (const void *p)
{
const_symtab_node n = (const_symtab_node) p;
return (hashval_t) decl_assembler_name_hash (DECL_ASSEMBLER_NAME (n->symbol.decl));
}
/* Returns nonzero if P1 and P2 are equal. */
static int
eq_assembler_name (const void *p1, const void *p2)
{
const_symtab_node n1 = (const_symtab_node) p1;
const_tree name = (const_tree)p2;
return (decl_assembler_name_equal (n1->symbol.decl, name));
}
/* Insert NODE to assembler name hash. */
static void
insert_to_assembler_name_hash (symtab_node node)
{
gcc_checking_assert (!node->symbol.previous_sharing_asm_name
&& !node->symbol.next_sharing_asm_name);
if (assembler_name_hash)
{
void **aslot;
tree name = DECL_ASSEMBLER_NAME (node->symbol.decl);
aslot = htab_find_slot_with_hash (assembler_name_hash, name,
decl_assembler_name_hash (name),
INSERT);
gcc_assert (*aslot != node);
node->symbol.next_sharing_asm_name = (symtab_node)*aslot;
if (*aslot != NULL)
((symtab_node)*aslot)->symbol.previous_sharing_asm_name = node;
*aslot = node;
}
}
/* Remove NODE from assembler name hash. */
static void
unlink_from_assembler_name_hash (symtab_node node)
{
if (assembler_name_hash)
{
if (node->symbol.next_sharing_asm_name)
node->symbol.next_sharing_asm_name->symbol.previous_sharing_asm_name
= node->symbol.previous_sharing_asm_name;
if (node->symbol.previous_sharing_asm_name)
{
node->symbol.previous_sharing_asm_name->symbol.next_sharing_asm_name
= node->symbol.next_sharing_asm_name;
}
else
{
tree name = DECL_ASSEMBLER_NAME (node->symbol.decl);
void **slot;
slot = htab_find_slot_with_hash (assembler_name_hash, name,
decl_assembler_name_hash (name),
NO_INSERT);
gcc_assert (*slot == node);
if (!node->symbol.next_sharing_asm_name)
htab_clear_slot (assembler_name_hash, slot);
else
*slot = node->symbol.next_sharing_asm_name;
}
}
}
/* Add node into symbol table. This function is not used directly, but via
cgraph/varpool node creation routines. */
void
symtab_register_node (symtab_node node)
{
struct symtab_node_base key;
symtab_node *slot;
node->symbol.next = symtab_nodes;
node->symbol.previous = NULL;
if (symtab_nodes)
symtab_nodes->symbol.previous = node;
symtab_nodes = node;
if (!symtab_hash)
symtab_hash = htab_create_ggc (10, hash_node, eq_node, NULL);
key.decl = node->symbol.decl;
slot = (symtab_node *) htab_find_slot (symtab_hash, &key, INSERT);
if (*slot == NULL)
*slot = node;
insert_to_assembler_name_hash (node);
node->symbol.order = symtab_order++;
ipa_empty_ref_list (&node->symbol.ref_list);
}
/* Make NODE to be the one symtab hash is pointing to. Used when reshaping tree
of inline clones. */
void
symtab_insert_node_to_hashtable (symtab_node node)
{
struct symtab_node_base key;
symtab_node *slot;
if (!symtab_hash)
symtab_hash = htab_create_ggc (10, hash_node, eq_node, NULL);
key.decl = node->symbol.decl;
slot = (symtab_node *) htab_find_slot (symtab_hash, &key, INSERT);
*slot = node;
}
/* Remove node from symbol table. This function is not used directly, but via
cgraph/varpool node removal routines. */
void
symtab_unregister_node (symtab_node node)
{
void **slot;
ipa_remove_all_references (&node->symbol.ref_list);
ipa_remove_all_refering (&node->symbol.ref_list);
@ -83,6 +214,46 @@ symtab_unregister_node (symtab_node node)
node->symbol.next->symbol.previous = node->symbol.previous;
node->symbol.next = NULL;
node->symbol.previous = NULL;
slot = htab_find_slot (symtab_hash, node, NO_INSERT);
if (*slot == node)
{
symtab_node replacement_node = NULL;
if (symtab_function_p (node))
replacement_node = (symtab_node)cgraph_find_replacement_node (cgraph (node));
if (!replacement_node)
htab_clear_slot (symtab_hash, slot);
else
*slot = replacement_node;
}
unlink_from_assembler_name_hash (node);
}
/* Return symbol table node associated with DECL, if any,
and NULL otherwise. */
symtab_node
symtab_get_node (const_tree decl)
{
symtab_node *slot;
struct symtab_node_base key;
gcc_checking_assert (TREE_CODE (decl) == FUNCTION_DECL
|| (TREE_CODE (decl) == VAR_DECL
&& (TREE_STATIC (decl) || DECL_EXTERNAL (decl)
|| in_lto_p)));
if (!symtab_hash)
return NULL;
key.decl = CONST_CAST2 (tree, const_tree, decl);
slot = (symtab_node *) htab_find_slot (symtab_hash, &key,
NO_INSERT);
if (slot)
return *slot;
return NULL;
}
/* Remove symtab NODE from the symbol table. */
@ -95,3 +266,71 @@ symtab_remove_node (symtab_node node)
else if (symtab_variable_p (node))
varpool_remove_node (varpool (node));
}
/* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME.
Return NULL if there's no such node. */
symtab_node
symtab_node_for_asm (const_tree asmname)
{
symtab_node node;
void **slot;
if (!assembler_name_hash)
{
assembler_name_hash =
htab_create_ggc (10, hash_node_by_assembler_name, eq_assembler_name,
NULL);
FOR_EACH_SYMBOL (node)
insert_to_assembler_name_hash (node);
}
slot = htab_find_slot_with_hash (assembler_name_hash, asmname,
decl_assembler_name_hash (asmname),
NO_INSERT);
if (slot)
{
node = (symtab_node) *slot;
return node;
}
return NULL;
}
/* Set the DECL_ASSEMBLER_NAME and update symtab hashtables. */
void
change_decl_assembler_name (tree decl, tree name)
{
symtab_node node = NULL;
/* We can have user ASM names on things, like global register variables, that
are not in the symbol table. */
if ((TREE_CODE (decl) == VAR_DECL
&& (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
|| TREE_CODE (decl) == FUNCTION_DECL)
node = symtab_get_node (decl);
if (!DECL_ASSEMBLER_NAME_SET_P (decl))
{
SET_DECL_ASSEMBLER_NAME (decl, name);
if (node)
insert_to_assembler_name_hash (node);
}
else
{
if (name == DECL_ASSEMBLER_NAME (decl))
return;
if (node)
unlink_from_assembler_name_hash (node);
if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
&& DECL_RTL_SET_P (decl))
warning (0, "%D renamed after being referenced in assembly", decl);
SET_DECL_ASSEMBLER_NAME (decl, name);
if (node)
insert_to_assembler_name_hash (node);
}
}
#include "gt-symtab.h"

View File

@ -48,9 +48,6 @@ along with GCC; see the file COPYING3. If not see
All variables supposed to be output into final file needs to be
explicitly marked by frontend via VARPOOL_FINALIZE_DECL function. */
/* Hash table used to convert declarations into nodes. */
static GTY((param_is (union symtab_node_def))) htab_t varpool_hash;
/* Queue of cgraph nodes scheduled to be lowered and output.
The queue is maintained via mark_needed_node, linked via node->next_needed
pointer.
@ -84,66 +81,20 @@ varpool_node_name (struct varpool_node *node)
return lang_hooks.decl_printable_name (node->symbol.decl, 2);
}
/* Returns a hash code for P. */
static hashval_t
hash_varpool_node (const void *p)
{
const struct varpool_node *n = (const struct varpool_node *) p;
return (hashval_t) DECL_UID (n->symbol.decl);
}
/* Returns nonzero if P1 and P2 are equal. */
static int
eq_varpool_node (const void *p1, const void *p2)
{
const struct varpool_node *n1 =
(const struct varpool_node *) p1;
const struct varpool_node *n2 =
(const struct varpool_node *) p2;
return DECL_UID (n1->symbol.decl) == DECL_UID (n2->symbol.decl);
}
/* Return varpool node assigned to DECL without creating new one. */
struct varpool_node *
varpool_get_node (const_tree decl)
{
struct varpool_node key, **slot;
gcc_assert (TREE_CODE (decl) == VAR_DECL
&& (TREE_STATIC (decl) || DECL_EXTERNAL (decl)));
if (!varpool_hash)
return NULL;
key.symbol.decl = CONST_CAST2 (tree, const_tree, decl);
slot = (struct varpool_node **)
htab_find_slot (varpool_hash, &key, NO_INSERT);
if (!slot)
return NULL;
return *slot;
}
/* Return varpool node assigned to DECL. Create new one when needed. */
struct varpool_node *
varpool_node (tree decl)
{
struct varpool_node key, *node, **slot;
struct varpool_node *node = varpool_get_node (decl);
gcc_assert (TREE_CODE (decl) == VAR_DECL
&& (TREE_STATIC (decl) || DECL_EXTERNAL (decl) || in_lto_p));
if (node)
return node;
if (!varpool_hash)
varpool_hash = htab_create_ggc (10, hash_varpool_node,
eq_varpool_node, NULL);
key.symbol.decl = decl;
slot = (struct varpool_node **)
htab_find_slot (varpool_hash, &key, INSERT);
if (*slot)
return *slot;
node = ggc_alloc_cleared_varpool_node ();
node->symbol.type = SYMTAB_VARIABLE;
node->symbol.decl = decl;
symtab_register_node ((symtab_node)node);
*slot = node;
return node;
}
@ -151,10 +102,6 @@ varpool_node (tree decl)
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);
symtab_unregister_node ((symtab_node)node);
if (varpool_first_unanalyzed_node == node)
@ -238,12 +185,9 @@ debug_varpool (void)
struct varpool_node *
varpool_node_for_asm (tree asmname)
{
struct varpool_node *node;
FOR_EACH_VARIABLE (node)
if (decl_assembler_name_equal (node->symbol.decl, asmname))
return node;
symtab_node node = symtab_node_for_asm (asmname);
if (node && symtab_variable_p (node))
return varpool (node);
return NULL;
}