]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/symtab.c
9e7c4df83e94e7084ed4b0baf5b768141d3fb4bb
[thirdparty/gcc.git] / gcc / symtab.c
1 /* Symbol table.
2 Copyright (C) 2012 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 "tm.h"
25 #include "tree.h"
26 #include "tree-inline.h"
27 #include "hashtab.h"
28 #include "ggc.h"
29 #include "cgraph.h"
30 #include "diagnostic.h"
31
32 /* Hash table used to convert declarations into nodes. */
33 static GTY((param_is (union symtab_node_def))) htab_t symtab_hash;
34 /* Hash table used to convert assembler names into nodes. */
35 static GTY((param_is (union symtab_node_def))) htab_t assembler_name_hash;
36
37 /* Linked list of symbol table nodes. */
38 symtab_node symtab_nodes;
39
40 /* The order index of the next symtab node to be created. This is
41 used so that we can sort the cgraph nodes in order by when we saw
42 them, to support -fno-toplevel-reorder. */
43 int symtab_order;
44
45 /* Returns a hash code for P. */
46
47 static hashval_t
48 hash_node (const void *p)
49 {
50 const_symtab_node n = (const_symtab_node ) p;
51 return (hashval_t) DECL_UID (n->symbol.decl);
52 }
53
54
55 /* Returns nonzero if P1 and P2 are equal. */
56
57 static int
58 eq_node (const void *p1, const void *p2)
59 {
60 const_symtab_node n1 = (const_symtab_node) p1;
61 const_symtab_node n2 = (const_symtab_node) p2;
62 return DECL_UID (n1->symbol.decl) == DECL_UID (n2->symbol.decl);
63 }
64
65 /* Returns a hash code for P. */
66
67 static hashval_t
68 hash_node_by_assembler_name (const void *p)
69 {
70 const_symtab_node n = (const_symtab_node) p;
71 return (hashval_t) decl_assembler_name_hash (DECL_ASSEMBLER_NAME (n->symbol.decl));
72 }
73
74 /* Returns nonzero if P1 and P2 are equal. */
75
76 static int
77 eq_assembler_name (const void *p1, const void *p2)
78 {
79 const_symtab_node n1 = (const_symtab_node) p1;
80 const_tree name = (const_tree)p2;
81 return (decl_assembler_name_equal (n1->symbol.decl, name));
82 }
83
84 /* Insert NODE to assembler name hash. */
85
86 static void
87 insert_to_assembler_name_hash (symtab_node node)
88 {
89 gcc_checking_assert (!node->symbol.previous_sharing_asm_name
90 && !node->symbol.next_sharing_asm_name);
91 if (assembler_name_hash)
92 {
93 void **aslot;
94 tree name = DECL_ASSEMBLER_NAME (node->symbol.decl);
95
96 aslot = htab_find_slot_with_hash (assembler_name_hash, name,
97 decl_assembler_name_hash (name),
98 INSERT);
99 gcc_assert (*aslot != node);
100 node->symbol.next_sharing_asm_name = (symtab_node)*aslot;
101 if (*aslot != NULL)
102 ((symtab_node)*aslot)->symbol.previous_sharing_asm_name = node;
103 *aslot = node;
104 }
105
106 }
107
108 /* Remove NODE from assembler name hash. */
109
110 static void
111 unlink_from_assembler_name_hash (symtab_node node)
112 {
113 if (assembler_name_hash)
114 {
115 if (node->symbol.next_sharing_asm_name)
116 node->symbol.next_sharing_asm_name->symbol.previous_sharing_asm_name
117 = node->symbol.previous_sharing_asm_name;
118 if (node->symbol.previous_sharing_asm_name)
119 {
120 node->symbol.previous_sharing_asm_name->symbol.next_sharing_asm_name
121 = node->symbol.next_sharing_asm_name;
122 }
123 else
124 {
125 tree name = DECL_ASSEMBLER_NAME (node->symbol.decl);
126 void **slot;
127 slot = htab_find_slot_with_hash (assembler_name_hash, name,
128 decl_assembler_name_hash (name),
129 NO_INSERT);
130 gcc_assert (*slot == node);
131 if (!node->symbol.next_sharing_asm_name)
132 htab_clear_slot (assembler_name_hash, slot);
133 else
134 *slot = node->symbol.next_sharing_asm_name;
135 }
136 }
137 }
138
139
140 /* Add node into symbol table. This function is not used directly, but via
141 cgraph/varpool node creation routines. */
142
143 void
144 symtab_register_node (symtab_node node)
145 {
146 struct symtab_node_base key;
147 symtab_node *slot;
148
149 node->symbol.next = symtab_nodes;
150 node->symbol.previous = NULL;
151 if (symtab_nodes)
152 symtab_nodes->symbol.previous = node;
153 symtab_nodes = node;
154
155 if (!symtab_hash)
156 symtab_hash = htab_create_ggc (10, hash_node, eq_node, NULL);
157 key.decl = node->symbol.decl;
158 slot = (symtab_node *) htab_find_slot (symtab_hash, &key, INSERT);
159 if (*slot == NULL)
160 *slot = node;
161
162 insert_to_assembler_name_hash (node);
163
164 node->symbol.order = symtab_order++;
165
166 ipa_empty_ref_list (&node->symbol.ref_list);
167 }
168
169 /* Make NODE to be the one symtab hash is pointing to. Used when reshaping tree
170 of inline clones. */
171
172 void
173 symtab_insert_node_to_hashtable (symtab_node node)
174 {
175 struct symtab_node_base key;
176 symtab_node *slot;
177
178 if (!symtab_hash)
179 symtab_hash = htab_create_ggc (10, hash_node, eq_node, NULL);
180 key.decl = node->symbol.decl;
181 slot = (symtab_node *) htab_find_slot (symtab_hash, &key, INSERT);
182 *slot = node;
183 }
184
185 /* Remove node from symbol table. This function is not used directly, but via
186 cgraph/varpool node removal routines. */
187
188 void
189 symtab_unregister_node (symtab_node node)
190 {
191 void **slot;
192 ipa_remove_all_references (&node->symbol.ref_list);
193 ipa_remove_all_refering (&node->symbol.ref_list);
194
195 if (node->symbol.same_comdat_group)
196 {
197 symtab_node prev;
198 for (prev = node->symbol.same_comdat_group;
199 prev->symbol.same_comdat_group != node;
200 prev = prev->symbol.same_comdat_group)
201 ;
202 if (node->symbol.same_comdat_group == prev)
203 prev->symbol.same_comdat_group = NULL;
204 else
205 prev->symbol.same_comdat_group = node->symbol.same_comdat_group;
206 node->symbol.same_comdat_group = NULL;
207 }
208
209 if (node->symbol.previous)
210 node->symbol.previous->symbol.next = node->symbol.next;
211 else
212 symtab_nodes = node->symbol.next;
213 if (node->symbol.next)
214 node->symbol.next->symbol.previous = node->symbol.previous;
215 node->symbol.next = NULL;
216 node->symbol.previous = NULL;
217
218 slot = htab_find_slot (symtab_hash, node, NO_INSERT);
219 if (*slot == node)
220 {
221 symtab_node replacement_node = NULL;
222 if (symtab_function_p (node))
223 replacement_node = (symtab_node)cgraph_find_replacement_node (cgraph (node));
224 if (!replacement_node)
225 htab_clear_slot (symtab_hash, slot);
226 else
227 *slot = replacement_node;
228 }
229 unlink_from_assembler_name_hash (node);
230 }
231
232 /* Return symbol table node associated with DECL, if any,
233 and NULL otherwise. */
234
235 symtab_node
236 symtab_get_node (const_tree decl)
237 {
238 symtab_node *slot;
239 struct symtab_node_base key;
240
241 gcc_checking_assert (TREE_CODE (decl) == FUNCTION_DECL
242 || (TREE_CODE (decl) == VAR_DECL
243 && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)
244 || in_lto_p)));
245
246 if (!symtab_hash)
247 return NULL;
248
249 key.decl = CONST_CAST2 (tree, const_tree, decl);
250
251 slot = (symtab_node *) htab_find_slot (symtab_hash, &key,
252 NO_INSERT);
253
254 if (slot)
255 return *slot;
256 return NULL;
257 }
258
259 /* Remove symtab NODE from the symbol table. */
260
261 void
262 symtab_remove_node (symtab_node node)
263 {
264 if (symtab_function_p (node))
265 cgraph_remove_node (cgraph (node));
266 else if (symtab_variable_p (node))
267 varpool_remove_node (varpool (node));
268 }
269
270 /* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME.
271 Return NULL if there's no such node. */
272
273 symtab_node
274 symtab_node_for_asm (const_tree asmname)
275 {
276 symtab_node node;
277 void **slot;
278
279 if (!assembler_name_hash)
280 {
281 assembler_name_hash =
282 htab_create_ggc (10, hash_node_by_assembler_name, eq_assembler_name,
283 NULL);
284 FOR_EACH_SYMBOL (node)
285 insert_to_assembler_name_hash (node);
286 }
287
288 slot = htab_find_slot_with_hash (assembler_name_hash, asmname,
289 decl_assembler_name_hash (asmname),
290 NO_INSERT);
291
292 if (slot)
293 {
294 node = (symtab_node) *slot;
295 return node;
296 }
297 return NULL;
298 }
299
300 /* Set the DECL_ASSEMBLER_NAME and update symtab hashtables. */
301
302 void
303 change_decl_assembler_name (tree decl, tree name)
304 {
305 symtab_node node = NULL;
306
307 /* We can have user ASM names on things, like global register variables, that
308 are not in the symbol table. */
309 if ((TREE_CODE (decl) == VAR_DECL
310 && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
311 || TREE_CODE (decl) == FUNCTION_DECL)
312 node = symtab_get_node (decl);
313 if (!DECL_ASSEMBLER_NAME_SET_P (decl))
314 {
315 SET_DECL_ASSEMBLER_NAME (decl, name);
316 if (node)
317 insert_to_assembler_name_hash (node);
318 }
319 else
320 {
321 if (name == DECL_ASSEMBLER_NAME (decl))
322 return;
323
324 if (node)
325 unlink_from_assembler_name_hash (node);
326 if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
327 && DECL_RTL_SET_P (decl))
328 warning (0, "%D renamed after being referenced in assembly", decl);
329
330 SET_DECL_ASSEMBLER_NAME (decl, name);
331 if (node)
332 insert_to_assembler_name_hash (node);
333 }
334 }
335
336 #include "gt-symtab.h"