Mercurial > hg > CbC > CbC_gcc
comparison 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 |
comparison
equal
deleted
inserted
replaced
56:3c8a44c06a95 | 63:b7f97abdc517 |
---|---|
1 /* Callgraph handling code. | 1 /* Callgraph handling code. |
2 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 | 2 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2010 |
3 Free Software Foundation, Inc. | 3 Free Software Foundation, Inc. |
4 Contributed by Jan Hubicka | 4 Contributed by Jan Hubicka |
5 | 5 |
6 This file is part of GCC. | 6 This file is part of GCC. |
7 | 7 |
103 const struct varpool_node *n2 = | 103 const struct varpool_node *n2 = |
104 (const struct varpool_node *) p2; | 104 (const struct varpool_node *) p2; |
105 return DECL_UID (n1->decl) == DECL_UID (n2->decl); | 105 return DECL_UID (n1->decl) == DECL_UID (n2->decl); |
106 } | 106 } |
107 | 107 |
108 /* Return varpool node assigned to DECL without creating new one. */ | |
109 struct varpool_node * | |
110 varpool_get_node (tree decl) | |
111 { | |
112 struct varpool_node key, **slot; | |
113 | |
114 gcc_assert (DECL_P (decl) && TREE_CODE (decl) != FUNCTION_DECL); | |
115 | |
116 if (!varpool_hash) | |
117 return NULL; | |
118 key.decl = decl; | |
119 slot = (struct varpool_node **) | |
120 htab_find_slot (varpool_hash, &key, INSERT); | |
121 return *slot; | |
122 } | |
123 | |
108 /* Return varpool node assigned to DECL. Create new one when needed. */ | 124 /* Return varpool node assigned to DECL. Create new one when needed. */ |
109 struct varpool_node * | 125 struct varpool_node * |
110 varpool_node (tree decl) | 126 varpool_node (tree decl) |
111 { | 127 { |
112 struct varpool_node key, *node, **slot; | 128 struct varpool_node key, *node, **slot; |
123 return *slot; | 139 return *slot; |
124 node = GGC_CNEW (struct varpool_node); | 140 node = GGC_CNEW (struct varpool_node); |
125 node->decl = decl; | 141 node->decl = decl; |
126 node->order = cgraph_order++; | 142 node->order = cgraph_order++; |
127 node->next = varpool_nodes; | 143 node->next = varpool_nodes; |
144 ipa_empty_ref_list (&node->ref_list); | |
145 if (varpool_nodes) | |
146 varpool_nodes->prev = node; | |
128 varpool_nodes = node; | 147 varpool_nodes = node; |
129 *slot = node; | 148 *slot = node; |
130 return node; | 149 return node; |
150 } | |
151 | |
152 /* Remove node from the varpool. */ | |
153 void | |
154 varpool_remove_node (struct varpool_node *node) | |
155 { | |
156 void **slot; | |
157 slot = htab_find_slot (varpool_hash, node, NO_INSERT); | |
158 gcc_assert (*slot == node); | |
159 htab_clear_slot (varpool_hash, slot); | |
160 gcc_assert (!varpool_assembled_nodes_queue); | |
161 if (!node->alias) | |
162 while (node->extra_name) | |
163 varpool_remove_node (node->extra_name); | |
164 if (node->next) | |
165 node->next->prev = node->prev; | |
166 if (node->prev) | |
167 node->prev->next = node->next; | |
168 else | |
169 { | |
170 if (node->alias && node->extra_name) | |
171 { | |
172 gcc_assert (node->extra_name->extra_name == node); | |
173 node->extra_name->extra_name = node->next; | |
174 } | |
175 else | |
176 { | |
177 gcc_assert (varpool_nodes == node); | |
178 varpool_nodes = node->next; | |
179 } | |
180 } | |
181 if (varpool_first_unanalyzed_node == node) | |
182 varpool_first_unanalyzed_node = node->next_needed; | |
183 if (node->next_needed) | |
184 node->next_needed->prev_needed = node->prev_needed; | |
185 else if (node->prev_needed) | |
186 { | |
187 gcc_assert (varpool_last_needed_node); | |
188 varpool_last_needed_node = node->prev_needed; | |
189 } | |
190 if (node->prev_needed) | |
191 node->prev_needed->next_needed = node->next_needed; | |
192 else if (node->next_needed) | |
193 { | |
194 gcc_assert (varpool_nodes_queue == node); | |
195 varpool_nodes_queue = node->next_needed; | |
196 } | |
197 if (node->same_comdat_group) | |
198 { | |
199 struct varpool_node *prev; | |
200 for (prev = node->same_comdat_group; | |
201 prev->same_comdat_group != node; | |
202 prev = prev->same_comdat_group) | |
203 ; | |
204 if (node->same_comdat_group == prev) | |
205 prev->same_comdat_group = NULL; | |
206 else | |
207 prev->same_comdat_group = node->same_comdat_group; | |
208 node->same_comdat_group = NULL; | |
209 } | |
210 ipa_remove_all_references (&node->ref_list); | |
211 ipa_remove_all_refering (&node->ref_list); | |
212 ggc_free (node); | |
131 } | 213 } |
132 | 214 |
133 /* Dump given cgraph node. */ | 215 /* Dump given cgraph node. */ |
134 void | 216 void |
135 dump_varpool_node (FILE *f, struct varpool_node *node) | 217 dump_varpool_node (FILE *f, struct varpool_node *node) |
137 fprintf (f, "%s:", varpool_node_name (node)); | 219 fprintf (f, "%s:", varpool_node_name (node)); |
138 fprintf (f, " availability:%s", | 220 fprintf (f, " availability:%s", |
139 cgraph_function_flags_ready | 221 cgraph_function_flags_ready |
140 ? cgraph_availability_names[cgraph_variable_initializer_availability (node)] | 222 ? cgraph_availability_names[cgraph_variable_initializer_availability (node)] |
141 : "not-ready"); | 223 : "not-ready"); |
224 if (DECL_ASSEMBLER_NAME_SET_P (node->decl)) | |
225 fprintf (f, " (asm: %s)", IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl))); | |
142 if (DECL_INITIAL (node->decl)) | 226 if (DECL_INITIAL (node->decl)) |
143 fprintf (f, " initialized"); | 227 fprintf (f, " initialized"); |
228 if (TREE_ASM_WRITTEN (node->decl)) | |
229 fprintf (f, " (asm written)"); | |
144 if (node->needed) | 230 if (node->needed) |
145 fprintf (f, " needed"); | 231 fprintf (f, " needed"); |
146 if (node->analyzed) | 232 if (node->analyzed) |
147 fprintf (f, " analyzed"); | 233 fprintf (f, " analyzed"); |
148 if (node->finalized) | 234 if (node->finalized) |
149 fprintf (f, " finalized"); | 235 fprintf (f, " finalized"); |
150 if (node->output) | 236 if (node->output) |
151 fprintf (f, " output"); | 237 fprintf (f, " output"); |
152 if (node->externally_visible) | 238 if (node->externally_visible) |
153 fprintf (f, " externally_visible"); | 239 fprintf (f, " externally_visible"); |
240 if (node->in_other_partition) | |
241 fprintf (f, " in_other_partition"); | |
242 else if (node->used_from_other_partition) | |
243 fprintf (f, " used_from_other_partition"); | |
154 fprintf (f, "\n"); | 244 fprintf (f, "\n"); |
245 fprintf (f, " References: "); | |
246 ipa_dump_references (f, &node->ref_list); | |
247 fprintf (f, " Refering this var: "); | |
248 ipa_dump_refering (f, &node->ref_list); | |
155 } | 249 } |
156 | 250 |
157 /* Dump the variable pool. */ | 251 /* Dump the variable pool. */ |
158 void | 252 void |
159 dump_varpool (FILE *f) | 253 dump_varpool (FILE *f) |
190 be analyzed and compiled. */ | 284 be analyzed and compiled. */ |
191 static void | 285 static void |
192 varpool_enqueue_needed_node (struct varpool_node *node) | 286 varpool_enqueue_needed_node (struct varpool_node *node) |
193 { | 287 { |
194 if (varpool_last_needed_node) | 288 if (varpool_last_needed_node) |
195 varpool_last_needed_node->next_needed = node; | 289 { |
290 varpool_last_needed_node->next_needed = node; | |
291 node->prev_needed = varpool_last_needed_node; | |
292 } | |
196 varpool_last_needed_node = node; | 293 varpool_last_needed_node = node; |
197 node->next_needed = NULL; | 294 node->next_needed = NULL; |
198 if (!varpool_nodes_queue) | 295 if (!varpool_nodes_queue) |
199 varpool_nodes_queue = node; | 296 varpool_nodes_queue = node; |
200 if (!varpool_first_unanalyzed_node) | 297 if (!varpool_first_unanalyzed_node) |
205 /* Notify finalize_compilation_unit that given node is reachable | 302 /* Notify finalize_compilation_unit that given node is reachable |
206 or needed. */ | 303 or needed. */ |
207 void | 304 void |
208 varpool_mark_needed_node (struct varpool_node *node) | 305 varpool_mark_needed_node (struct varpool_node *node) |
209 { | 306 { |
307 if (node->alias && node->extra_name) | |
308 node = node->extra_name; | |
210 if (!node->needed && node->finalized | 309 if (!node->needed && node->finalized |
211 && !TREE_ASM_WRITTEN (node->decl)) | 310 && !TREE_ASM_WRITTEN (node->decl)) |
212 varpool_enqueue_needed_node (node); | 311 varpool_enqueue_needed_node (node); |
213 node->needed = 1; | 312 node->needed = 1; |
214 } | 313 } |
215 | 314 |
216 /* Reset the queue of needed nodes. */ | 315 /* Reset the queue of needed nodes. */ |
217 static void | 316 void |
218 varpool_reset_queue (void) | 317 varpool_reset_queue (void) |
219 { | 318 { |
220 varpool_last_needed_node = NULL; | 319 varpool_last_needed_node = NULL; |
221 varpool_nodes_queue = NULL; | 320 varpool_nodes_queue = NULL; |
222 varpool_first_unanalyzed_node = NULL; | 321 varpool_first_unanalyzed_node = NULL; |
226 either outside this translation unit, something magic in the system | 325 either outside this translation unit, something magic in the system |
227 configury */ | 326 configury */ |
228 bool | 327 bool |
229 decide_is_variable_needed (struct varpool_node *node, tree decl) | 328 decide_is_variable_needed (struct varpool_node *node, tree decl) |
230 { | 329 { |
330 if (node->used_from_other_partition) | |
331 return true; | |
231 /* If the user told us it is used, then it must be so. */ | 332 /* If the user told us it is used, then it must be so. */ |
232 if ((node->externally_visible && !DECL_COMDAT (decl)) | 333 if ((node->externally_visible && !DECL_COMDAT (decl)) |
233 || node->force_output) | 334 || node->force_output) |
234 return true; | |
235 | |
236 /* ??? If the assembler name is set by hand, it is possible to assemble | |
237 the name later after finalizing the function and the fact is noticed | |
238 in assemble_name then. This is arguably a bug. */ | |
239 if (DECL_ASSEMBLER_NAME_SET_P (decl) | |
240 && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))) | |
241 return true; | 335 return true; |
242 | 336 |
243 /* Externally visible variables must be output. The exception is | 337 /* Externally visible variables must be output. The exception is |
244 COMDAT variables that must be output only when they are needed. */ | 338 COMDAT variables that must be output only when they are needed. */ |
245 if (TREE_PUBLIC (decl) | 339 if (TREE_PUBLIC (decl) |
278 void | 372 void |
279 varpool_finalize_decl (tree decl) | 373 varpool_finalize_decl (tree decl) |
280 { | 374 { |
281 struct varpool_node *node = varpool_node (decl); | 375 struct varpool_node *node = varpool_node (decl); |
282 | 376 |
283 /* FIXME: We don't really stream varpool datastructure and instead rebuild it | |
284 by varpool_finalize_decl. This is not quite correct since this way we can't | |
285 attach any info to varpool. Eventually we will want to stream varpool nodes | |
286 and the flags. | |
287 | |
288 For the moment just prevent analysis of varpool nodes to happen again, so | |
289 we will re-try to compute "address_taken" flag of varpool that breaks | |
290 in presence of clones. */ | |
291 if (in_lto_p) | |
292 node->analyzed = true; | |
293 | |
294 /* The first declaration of a variable that comes through this function | 377 /* The first declaration of a variable that comes through this function |
295 decides whether it is global (in C, has external linkage) | 378 decides whether it is global (in C, has external linkage) |
296 or local (in C, has internal linkage). So do nothing more | 379 or local (in C, has internal linkage). So do nothing more |
297 if this function has already run. */ | 380 if this function has already run. */ |
298 if (node->finalized) | 381 if (node->finalized) |
302 return; | 385 return; |
303 } | 386 } |
304 if (node->needed) | 387 if (node->needed) |
305 varpool_enqueue_needed_node (node); | 388 varpool_enqueue_needed_node (node); |
306 node->finalized = true; | 389 node->finalized = true; |
390 if (TREE_THIS_VOLATILE (decl) || DECL_PRESERVE_P (decl)) | |
391 node->force_output = true; | |
307 | 392 |
308 if (decide_is_variable_needed (node, decl)) | 393 if (decide_is_variable_needed (node, decl)) |
309 varpool_mark_needed_node (node); | 394 varpool_mark_needed_node (node); |
310 /* Since we reclaim unreachable nodes at the end of every language | 395 /* Since we reclaim unreachable nodes at the end of every language |
311 level unit, we need to be conservative about possible entry points | 396 level unit, we need to be conservative about possible entry points |
338 variables or functions and add them into the worklists. */ | 423 variables or functions and add them into the worklists. */ |
339 bool | 424 bool |
340 varpool_analyze_pending_decls (void) | 425 varpool_analyze_pending_decls (void) |
341 { | 426 { |
342 bool changed = false; | 427 bool changed = false; |
343 timevar_push (TV_CGRAPH); | 428 |
344 | 429 timevar_push (TV_VARPOOL); |
345 while (varpool_first_unanalyzed_node) | 430 while (varpool_first_unanalyzed_node) |
346 { | 431 { |
347 tree decl = varpool_first_unanalyzed_node->decl; | 432 struct varpool_node *node = varpool_first_unanalyzed_node, *next; |
348 bool analyzed = varpool_first_unanalyzed_node->analyzed; | 433 tree decl = node->decl; |
434 bool analyzed = node->analyzed; | |
349 | 435 |
350 varpool_first_unanalyzed_node->analyzed = true; | 436 varpool_first_unanalyzed_node->analyzed = true; |
351 | 437 |
352 varpool_first_unanalyzed_node = varpool_first_unanalyzed_node->next_needed; | 438 varpool_first_unanalyzed_node = varpool_first_unanalyzed_node->next_needed; |
353 | 439 |
354 /* When reading back varpool at LTO time, we re-construct the queue in order | 440 /* When reading back varpool at LTO time, we re-construct the queue in order |
355 to have "needed" list right by inserting all needed nodes into varpool. | 441 to have "needed" list right by inserting all needed nodes into varpool. |
356 We however don't want to re-analyze already analyzed nodes. */ | 442 We however don't want to re-analyze already analyzed nodes. */ |
357 if (!analyzed) | 443 if (!analyzed) |
358 { | 444 { |
359 gcc_assert (!in_lto_p); | 445 gcc_assert (!in_lto_p || cgraph_function_flags_ready); |
360 /* Compute the alignment early so function body expanders are | 446 /* Compute the alignment early so function body expanders are |
361 already informed about increased alignment. */ | 447 already informed about increased alignment. */ |
362 align_variable (decl, 0); | 448 align_variable (decl, 0); |
363 } | 449 } |
364 if (DECL_INITIAL (decl)) | 450 if (DECL_INITIAL (decl)) |
365 record_references_in_initializer (decl, analyzed); | 451 record_references_in_initializer (decl, analyzed); |
452 if (node->same_comdat_group) | |
453 { | |
454 for (next = node->same_comdat_group; | |
455 next != node; | |
456 next = next->same_comdat_group) | |
457 varpool_mark_needed_node (next); | |
458 } | |
366 changed = true; | 459 changed = true; |
367 } | 460 } |
368 timevar_pop (TV_CGRAPH); | 461 timevar_pop (TV_VARPOOL); |
369 return changed; | 462 return changed; |
370 } | 463 } |
371 | 464 |
372 /* Output one variable, if necessary. Return whether we output it. */ | 465 /* Output one variable, if necessary. Return whether we output it. */ |
373 bool | 466 bool |
375 { | 468 { |
376 tree decl = node->decl; | 469 tree decl = node->decl; |
377 | 470 |
378 if (!TREE_ASM_WRITTEN (decl) | 471 if (!TREE_ASM_WRITTEN (decl) |
379 && !node->alias | 472 && !node->alias |
473 && !node->in_other_partition | |
380 && !DECL_EXTERNAL (decl) | 474 && !DECL_EXTERNAL (decl) |
381 && (TREE_CODE (decl) != VAR_DECL || !DECL_HAS_VALUE_EXPR_P (decl))) | 475 && (TREE_CODE (decl) != VAR_DECL || !DECL_HAS_VALUE_EXPR_P (decl))) |
382 { | 476 { |
383 assemble_variable (decl, 0, 1, 0); | 477 assemble_variable (decl, 0, 1, 0); |
384 if (TREE_ASM_WRITTEN (decl)) | 478 if (TREE_ASM_WRITTEN (decl)) |
385 { | 479 { |
480 struct varpool_node *alias; | |
481 | |
386 node->next_needed = varpool_assembled_nodes_queue; | 482 node->next_needed = varpool_assembled_nodes_queue; |
483 node->prev_needed = NULL; | |
484 if (varpool_assembled_nodes_queue) | |
485 varpool_assembled_nodes_queue->prev_needed = node; | |
387 varpool_assembled_nodes_queue = node; | 486 varpool_assembled_nodes_queue = node; |
388 node->finalized = 1; | 487 node->finalized = 1; |
488 | |
489 /* Also emit any extra name aliases. */ | |
490 for (alias = node->extra_name; alias; alias = alias->next) | |
491 { | |
492 /* Update linkage fields in case they've changed. */ | |
493 DECL_WEAK (alias->decl) = DECL_WEAK (decl); | |
494 TREE_PUBLIC (alias->decl) = TREE_PUBLIC (decl); | |
495 DECL_VISIBILITY (alias->decl) = DECL_VISIBILITY (decl); | |
496 assemble_alias (alias->decl, DECL_ASSEMBLER_NAME (decl)); | |
497 } | |
498 | |
389 return true; | 499 return true; |
390 } | 500 } |
391 } | 501 } |
392 | 502 |
393 return false; | 503 return false; |
440 bool changed = false; | 550 bool changed = false; |
441 | 551 |
442 if (errorcount || sorrycount) | 552 if (errorcount || sorrycount) |
443 return false; | 553 return false; |
444 | 554 |
555 timevar_push (TV_VAROUT); | |
445 /* EH might mark decls as needed during expansion. This should be safe since | 556 /* EH might mark decls as needed during expansion. This should be safe since |
446 we don't create references to new function, but it should not be used | 557 we don't create references to new function, but it should not be used |
447 elsewhere. */ | 558 elsewhere. */ |
448 varpool_analyze_pending_decls (); | 559 varpool_analyze_pending_decls (); |
449 | 560 |
453 | 564 |
454 varpool_nodes_queue = varpool_nodes_queue->next_needed; | 565 varpool_nodes_queue = varpool_nodes_queue->next_needed; |
455 if (varpool_assemble_decl (node)) | 566 if (varpool_assemble_decl (node)) |
456 changed = true; | 567 changed = true; |
457 else | 568 else |
458 node->next_needed = NULL; | 569 { |
570 node->prev_needed = NULL; | |
571 node->next_needed = NULL; | |
572 } | |
459 } | 573 } |
460 /* varpool_nodes_queue is now empty, clear the pointer to the last element | 574 /* varpool_nodes_queue is now empty, clear the pointer to the last element |
461 in the queue. */ | 575 in the queue. */ |
462 varpool_last_needed_node = NULL; | 576 varpool_last_needed_node = NULL; |
577 timevar_pop (TV_VAROUT); | |
463 return changed; | 578 return changed; |
464 } | 579 } |
465 | 580 |
466 /* Remove all elements from the queue so we can re-use it for debug output. */ | 581 /* Remove all elements from the queue so we can re-use it for debug output. */ |
467 void | 582 void |
475 while (varpool_nodes_queue) | 590 while (varpool_nodes_queue) |
476 { | 591 { |
477 struct varpool_node *node = varpool_nodes_queue; | 592 struct varpool_node *node = varpool_nodes_queue; |
478 varpool_nodes_queue = varpool_nodes_queue->next_needed; | 593 varpool_nodes_queue = varpool_nodes_queue->next_needed; |
479 node->next_needed = NULL; | 594 node->next_needed = NULL; |
595 node->prev_needed = NULL; | |
480 } | 596 } |
481 /* varpool_nodes_queue is now empty, clear the pointer to the last element | 597 /* varpool_nodes_queue is now empty, clear the pointer to the last element |
482 in the queue. */ | 598 in the queue. */ |
483 varpool_last_needed_node = NULL; | 599 varpool_last_needed_node = NULL; |
484 } | 600 } |
505 varpool_finalize_decl (new_decl); | 621 varpool_finalize_decl (new_decl); |
506 | 622 |
507 return new_node->decl; | 623 return new_node->decl; |
508 } | 624 } |
509 | 625 |
626 /* Attempt to mark ALIAS as an alias to DECL. Return TRUE if successful. | |
627 Extra name aliases are output whenever DECL is output. */ | |
628 | |
629 bool | |
630 varpool_extra_name_alias (tree alias, tree decl) | |
631 { | |
632 struct varpool_node key, *alias_node, *decl_node, **slot; | |
633 | |
634 #ifndef ASM_OUTPUT_DEF | |
635 /* If aliases aren't supported by the assembler, fail. */ | |
636 return false; | |
637 #endif | |
638 | |
639 gcc_assert (TREE_CODE (decl) == VAR_DECL); | |
640 gcc_assert (TREE_CODE (alias) == VAR_DECL); | |
641 /* Make sure the hash table has been created. */ | |
642 decl_node = varpool_node (decl); | |
643 | |
644 key.decl = alias; | |
645 | |
646 slot = (struct varpool_node **) htab_find_slot (varpool_hash, &key, INSERT); | |
647 | |
648 /* If the varpool_node has been already created, fail. */ | |
649 if (*slot) | |
650 return false; | |
651 | |
652 alias_node = GGC_CNEW (struct varpool_node); | |
653 alias_node->decl = alias; | |
654 alias_node->alias = 1; | |
655 alias_node->extra_name = decl_node; | |
656 alias_node->next = decl_node->extra_name; | |
657 ipa_empty_ref_list (&alias_node->ref_list); | |
658 if (decl_node->extra_name) | |
659 decl_node->extra_name->prev = alias_node; | |
660 decl_node->extra_name = alias_node; | |
661 *slot = alias_node; | |
662 return true; | |
663 } | |
664 | |
510 #include "gt-varpool.h" | 665 #include "gt-varpool.h" |