Mercurial > hg > CbC > CbC_gcc
annotate gcc/cgraphunit.c @ 132:d34655255c78
update gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 10:21:07 +0900 |
parents | 84e7813d76e9 |
children | 1830386684a0 |
rev | line source |
---|---|
111 | 1 /* Driver of optimization process |
131 | 2 Copyright (C) 2003-2018 Free Software Foundation, Inc. |
0 | 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 | |
111 | 21 /* This module implements main driver of compilation process. |
0 | 22 |
23 The main scope of this file is to act as an interface in between | |
111 | 24 tree based frontends and the backend. |
0 | 25 |
26 The front-end is supposed to use following functionality: | |
27 | |
111 | 28 - finalize_function |
0 | 29 |
30 This function is called once front-end has parsed whole body of function | |
31 and it is certain that the function body nor the declaration will change. | |
32 | |
33 (There is one exception needed for implementing GCC extern inline | |
34 function.) | |
35 | |
111 | 36 - varpool_finalize_decl |
0 | 37 |
38 This function has same behavior as the above but is used for static | |
39 variables. | |
40 | |
111 | 41 - add_asm_node |
42 | |
43 Insert new toplevel ASM statement | |
44 | |
45 - finalize_compilation_unit | |
0 | 46 |
47 This function is called once (source level) compilation unit is finalized | |
48 and it will no longer change. | |
49 | |
111 | 50 The symbol table is constructed starting from the trivially needed |
51 symbols finalized by the frontend. Functions are lowered into | |
52 GIMPLE representation and callgraph/reference lists are constructed. | |
53 Those are used to discover other necessary functions and variables. | |
54 | |
55 At the end the bodies of unreachable functions are removed. | |
0 | 56 |
57 The function can be called multiple times when multiple source level | |
111 | 58 compilation units are combined. |
59 | |
60 - compile | |
61 | |
62 This passes control to the back-end. Optimizations are performed and | |
63 final assembler is generated. This is done in the following way. Note | |
64 that with link time optimization the process is split into three | |
65 stages (compile time, linktime analysis and parallel linktime as | |
66 indicated bellow). | |
67 | |
68 Compile time: | |
69 | |
70 1) Inter-procedural optimization. | |
71 (ipa_passes) | |
72 | |
73 This part is further split into: | |
74 | |
75 a) early optimizations. These are local passes executed in | |
76 the topological order on the callgraph. | |
77 | |
78 The purpose of early optimiations is to optimize away simple | |
79 things that may otherwise confuse IP analysis. Very simple | |
80 propagation across the callgraph is done i.e. to discover | |
81 functions without side effects and simple inlining is performed. | |
82 | |
83 b) early small interprocedural passes. | |
84 | |
85 Those are interprocedural passes executed only at compilation | |
86 time. These include, for example, transational memory lowering, | |
87 unreachable code removal and other simple transformations. | |
88 | |
89 c) IP analysis stage. All interprocedural passes do their | |
90 analysis. | |
91 | |
92 Interprocedural passes differ from small interprocedural | |
93 passes by their ability to operate across whole program | |
94 at linktime. Their analysis stage is performed early to | |
95 both reduce linking times and linktime memory usage by | |
96 not having to represent whole program in memory. | |
97 | |
98 d) LTO sreaming. When doing LTO, everything important gets | |
99 streamed into the object file. | |
100 | |
101 Compile time and or linktime analysis stage (WPA): | |
102 | |
103 At linktime units gets streamed back and symbol table is | |
104 merged. Function bodies are not streamed in and not | |
105 available. | |
106 e) IP propagation stage. All IP passes execute their | |
107 IP propagation. This is done based on the earlier analysis | |
108 without having function bodies at hand. | |
109 f) Ltrans streaming. When doing WHOPR LTO, the program | |
110 is partitioned and streamed into multple object files. | |
111 | |
112 Compile time and/or parallel linktime stage (ltrans) | |
113 | |
114 Each of the object files is streamed back and compiled | |
115 separately. Now the function bodies becomes available | |
116 again. | |
117 | |
118 2) Virtual clone materialization | |
119 (cgraph_materialize_clone) | |
120 | |
121 IP passes can produce copies of existing functoins (such | |
122 as versioned clones or inline clones) without actually | |
123 manipulating their bodies by creating virtual clones in | |
124 the callgraph. At this time the virtual clones are | |
125 turned into real functions | |
126 3) IP transformation | |
127 | |
128 All IP passes transform function bodies based on earlier | |
129 decision of the IP propagation. | |
130 | |
131 4) late small IP passes | |
132 | |
133 Simple IP passes working within single program partition. | |
134 | |
135 5) Expansion | |
136 (expand_all_functions) | |
137 | |
138 At this stage functions that needs to be output into | |
139 assembler are identified and compiled in topological order | |
140 6) Output of variables and aliases | |
141 Now it is known what variable references was not optimized | |
142 out and thus all variables are output to the file. | |
143 | |
144 Note that with -fno-toplevel-reorder passes 5 and 6 | |
145 are combined together in cgraph_output_in_order. | |
146 | |
147 Finally there are functions to manipulate the callgraph from | |
148 backend. | |
149 - cgraph_add_new_function is used to add backend produced | |
150 functions introduced after the unit is finalized. | |
151 The functions are enqueue for later processing and inserted | |
152 into callgraph with cgraph_process_new_functions. | |
153 | |
154 - cgraph_function_versioning | |
155 | |
156 produces a copy of function into new one (a version) | |
157 and apply simple transformations | |
158 */ | |
0 | 159 |
160 #include "config.h" | |
161 #include "system.h" | |
162 #include "coretypes.h" | |
111 | 163 #include "backend.h" |
164 #include "target.h" | |
0 | 165 #include "rtl.h" |
111 | 166 #include "tree.h" |
167 #include "gimple.h" | |
168 #include "cfghooks.h" | |
169 #include "regset.h" /* FIXME: For reg_obstack. */ | |
170 #include "alloc-pool.h" | |
171 #include "tree-pass.h" | |
172 #include "stringpool.h" | |
173 #include "gimple-ssa.h" | |
174 #include "cgraph.h" | |
175 #include "coverage.h" | |
176 #include "lto-streamer.h" | |
177 #include "fold-const.h" | |
178 #include "varasm.h" | |
179 #include "stor-layout.h" | |
180 #include "output.h" | |
181 #include "cfgcleanup.h" | |
182 #include "gimple-fold.h" | |
183 #include "gimplify.h" | |
184 #include "gimple-iterator.h" | |
185 #include "gimplify-me.h" | |
186 #include "tree-cfg.h" | |
187 #include "tree-into-ssa.h" | |
188 #include "tree-ssa.h" | |
0 | 189 #include "langhooks.h" |
190 #include "toplev.h" | |
191 #include "debug.h" | |
111 | 192 #include "symbol-summary.h" |
193 #include "tree-vrp.h" | |
194 #include "ipa-prop.h" | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
195 #include "gimple-pretty-print.h" |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
196 #include "plugin.h" |
111 | 197 #include "ipa-fnsummary.h" |
198 #include "ipa-utils.h" | |
199 #include "except.h" | |
200 #include "cfgloop.h" | |
201 #include "context.h" | |
202 #include "pass_manager.h" | |
203 #include "tree-nested.h" | |
204 #include "dbgcnt.h" | |
205 #include "lto-section-names.h" | |
206 #include "stringpool.h" | |
207 #include "attribs.h" | |
208 | |
209 /* Queue of cgraph nodes scheduled to be added into cgraph. This is a | |
210 secondary queue used during optimization to accommodate passes that | |
211 may generate new functions that need to be optimized and expanded. */ | |
212 vec<cgraph_node *> cgraph_new_nodes; | |
213 | |
214 static void expand_all_functions (void); | |
215 static void mark_functions_to_output (void); | |
216 static void handle_alias_pairs (void); | |
0 | 217 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
218 /* Used for vtable lookup in thunk adjusting. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
219 static GTY (()) tree vtable_entry_type; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
220 |
111 | 221 /* Return true if this symbol is a function from the C frontend specified |
222 directly in RTL form (with "__RTL"). */ | |
0 | 223 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
224 bool |
111 | 225 symtab_node::native_rtl_p () const |
0 | 226 { |
111 | 227 if (TREE_CODE (decl) != FUNCTION_DECL) |
228 return false; | |
229 if (!DECL_STRUCT_FUNCTION (decl)) | |
230 return false; | |
231 return DECL_STRUCT_FUNCTION (decl)->curr_properties & PROP_rtl; | |
232 } | |
233 | |
234 /* Determine if symbol declaration is needed. That is, visible to something | |
235 either outside this translation unit, something magic in the system | |
236 configury */ | |
237 bool | |
238 symtab_node::needed_p (void) | |
239 { | |
240 /* Double check that no one output the function into assembly file | |
241 early. */ | |
242 if (!native_rtl_p ()) | |
243 gcc_checking_assert | |
244 (!DECL_ASSEMBLER_NAME_SET_P (decl) | |
245 || !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))); | |
246 | |
247 if (!definition) | |
248 return false; | |
249 | |
250 if (DECL_EXTERNAL (decl)) | |
251 return false; | |
252 | |
0 | 253 /* If the user told us it is used, then it must be so. */ |
111 | 254 if (force_output) |
0 | 255 return true; |
256 | |
111 | 257 /* ABI forced symbols are needed when they are external. */ |
258 if (forced_by_abi && TREE_PUBLIC (decl)) | |
0 | 259 return true; |
260 | |
111 | 261 /* Keep constructors, destructors and virtual functions. */ |
262 if (TREE_CODE (decl) == FUNCTION_DECL | |
263 && (DECL_STATIC_CONSTRUCTOR (decl) || DECL_STATIC_DESTRUCTOR (decl))) | |
264 return true; | |
265 | |
266 /* Externally visible variables must be output. The exception is | |
267 COMDAT variables that must be output only when they are needed. */ | |
268 if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl)) | |
0 | 269 return true; |
270 | |
271 return false; | |
272 } | |
273 | |
111 | 274 /* Head and terminator of the queue of nodes to be processed while building |
275 callgraph. */ | |
276 | |
277 static symtab_node symtab_terminator; | |
278 static symtab_node *queued_nodes = &symtab_terminator; | |
279 | |
280 /* Add NODE to queue starting at QUEUED_NODES. | |
281 The queue is linked via AUX pointers and terminated by pointer to 1. */ | |
282 | |
283 static void | |
284 enqueue_node (symtab_node *node) | |
285 { | |
286 if (node->aux) | |
287 return; | |
288 gcc_checking_assert (queued_nodes); | |
289 node->aux = queued_nodes; | |
290 queued_nodes = node; | |
291 } | |
292 | |
0 | 293 /* Process CGRAPH_NEW_FUNCTIONS and perform actions necessary to add these |
294 functions into callgraph in a way so they look like ordinary reachable | |
295 functions inserted into callgraph already at construction time. */ | |
296 | |
111 | 297 void |
298 symbol_table::process_new_functions (void) | |
0 | 299 { |
300 tree fndecl; | |
111 | 301 |
302 if (!cgraph_new_nodes.exists ()) | |
303 return; | |
304 | |
305 handle_alias_pairs (); | |
0 | 306 /* Note that this queue may grow as its being processed, as the new |
307 functions may generate new ones. */ | |
111 | 308 for (unsigned i = 0; i < cgraph_new_nodes.length (); i++) |
0 | 309 { |
111 | 310 cgraph_node *node = cgraph_new_nodes[i]; |
0 | 311 fndecl = node->decl; |
111 | 312 switch (state) |
0 | 313 { |
111 | 314 case CONSTRUCTION: |
0 | 315 /* At construction time we just need to finalize function and move |
316 it into reachable functions list. */ | |
317 | |
111 | 318 cgraph_node::finalize_function (fndecl, false); |
319 call_cgraph_insertion_hooks (node); | |
320 enqueue_node (node); | |
0 | 321 break; |
322 | |
111 | 323 case IPA: |
324 case IPA_SSA: | |
325 case IPA_SSA_AFTER_INLINING: | |
0 | 326 /* When IPA optimization already started, do all essential |
327 transformations that has been already performed on the whole | |
328 cgraph but not on this function. */ | |
329 | |
330 gimple_register_cfg_hooks (); | |
331 if (!node->analyzed) | |
111 | 332 node->analyze (); |
0 | 333 push_cfun (DECL_STRUCT_FUNCTION (fndecl)); |
111 | 334 if ((state == IPA_SSA || state == IPA_SSA_AFTER_INLINING) |
0 | 335 && !gimple_in_ssa_p (DECL_STRUCT_FUNCTION (fndecl))) |
111 | 336 { |
337 bool summaried_computed = ipa_fn_summaries != NULL; | |
338 g->get_passes ()->execute_early_local_passes (); | |
339 /* Early passes compure inline parameters to do inlining | |
340 and splitting. This is redundant for functions added late. | |
341 Just throw away whatever it did. */ | |
342 if (!summaried_computed) | |
343 ipa_free_fn_summary (); | |
344 } | |
345 else if (ipa_fn_summaries != NULL) | |
346 compute_fn_summary (node, true); | |
0 | 347 free_dominance_info (CDI_POST_DOMINATORS); |
348 free_dominance_info (CDI_DOMINATORS); | |
349 pop_cfun (); | |
111 | 350 call_cgraph_insertion_hooks (node); |
0 | 351 break; |
352 | |
111 | 353 case EXPANSION: |
0 | 354 /* Functions created during expansion shall be compiled |
355 directly. */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
356 node->process = 0; |
111 | 357 call_cgraph_insertion_hooks (node); |
358 node->expand (); | |
0 | 359 break; |
360 | |
361 default: | |
362 gcc_unreachable (); | |
363 break; | |
364 } | |
365 } | |
111 | 366 |
367 cgraph_new_nodes.release (); | |
0 | 368 } |
369 | |
370 /* As an GCC extension we allow redefinition of the function. The | |
371 semantics when both copies of bodies differ is not well defined. | |
372 We replace the old body with new body so in unit at a time mode | |
373 we always use new body, while in normal mode we may end up with | |
374 old body inlined into some functions and new body expanded and | |
375 inlined in others. | |
376 | |
377 ??? It may make more sense to use one body for inlining and other | |
378 body for expanding the function but this is difficult to do. */ | |
379 | |
111 | 380 void |
381 cgraph_node::reset (void) | |
0 | 382 { |
111 | 383 /* If process is set, then we have already begun whole-unit analysis. |
0 | 384 This is *not* testing for whether we've already emitted the function. |
385 That case can be sort-of legitimately seen with real function redefinition | |
386 errors. I would argue that the front end should never present us with | |
387 such a case, but don't enforce that for now. */ | |
111 | 388 gcc_assert (!process); |
0 | 389 |
390 /* Reset our data structures so we can analyze the function again. */ | |
111 | 391 memset (&local, 0, sizeof (local)); |
392 memset (&global, 0, sizeof (global)); | |
393 memset (&rtl, 0, sizeof (rtl)); | |
394 analyzed = false; | |
395 definition = false; | |
396 alias = false; | |
397 transparent_alias = false; | |
398 weakref = false; | |
399 cpp_implicit_alias = false; | |
400 | |
401 remove_callees (); | |
402 remove_all_references (); | |
403 } | |
404 | |
405 /* Return true when there are references to the node. INCLUDE_SELF is | |
406 true if a self reference counts as a reference. */ | |
407 | |
408 bool | |
409 symtab_node::referred_to_p (bool include_self) | |
410 { | |
411 ipa_ref *ref = NULL; | |
412 | |
413 /* See if there are any references at all. */ | |
414 if (iterate_referring (0, ref)) | |
415 return true; | |
416 /* For functions check also calls. */ | |
417 cgraph_node *cn = dyn_cast <cgraph_node *> (this); | |
418 if (cn && cn->callers) | |
0 | 419 { |
111 | 420 if (include_self) |
421 return true; | |
422 for (cgraph_edge *e = cn->callers; e; e = e->next_caller) | |
423 if (e->caller != this) | |
424 return true; | |
0 | 425 } |
111 | 426 return false; |
0 | 427 } |
428 | |
429 /* DECL has been parsed. Take it, queue it, compile it at the whim of the | |
111 | 430 logic in effect. If NO_COLLECT is true, then our caller cannot stand to have |
0 | 431 the garbage collector run at the moment. We would need to either create |
432 a new GC context, or just not compile right now. */ | |
433 | |
434 void | |
111 | 435 cgraph_node::finalize_function (tree decl, bool no_collect) |
0 | 436 { |
111 | 437 cgraph_node *node = cgraph_node::get_create (decl); |
438 | |
439 if (node->definition) | |
440 { | |
441 /* Nested functions should only be defined once. */ | |
442 gcc_assert (!DECL_CONTEXT (decl) | |
443 || TREE_CODE (DECL_CONTEXT (decl)) != FUNCTION_DECL); | |
444 node->reset (); | |
445 node->local.redefined_extern_inline = true; | |
446 } | |
447 | |
448 /* Set definition first before calling notice_global_symbol so that | |
449 it is available to notice_global_symbol. */ | |
450 node->definition = true; | |
0 | 451 notice_global_symbol (decl); |
452 node->lowered = DECL_STRUCT_FUNCTION (decl)->cfg != NULL; | |
111 | 453 if (!flag_toplevel_reorder) |
454 node->no_reorder = true; | |
455 | |
456 /* With -fkeep-inline-functions we are keeping all inline functions except | |
457 for extern inline ones. */ | |
458 if (flag_keep_inline_functions | |
459 && DECL_DECLARED_INLINE_P (decl) | |
460 && !DECL_EXTERNAL (decl) | |
461 && !DECL_DISREGARD_INLINE_LIMITS (decl)) | |
462 node->force_output = 1; | |
463 | |
464 /* __RTL functions were already output as soon as they were parsed (due | |
465 to the large amount of global state in the backend). | |
466 Mark such functions as "force_output" to reflect the fact that they | |
467 will be in the asm file when considering the symbols they reference. | |
468 The attempt to output them later on will bail out immediately. */ | |
469 if (node->native_rtl_p ()) | |
470 node->force_output = 1; | |
471 | |
472 /* When not optimizing, also output the static functions. (see | |
473 PR24561), but don't do so for always_inline functions, functions | |
474 declared inline and nested functions. These were optimized out | |
475 in the original implementation and it is unclear whether we want | |
476 to change the behavior here. */ | |
477 if (((!opt_for_fn (decl, optimize) || flag_keep_static_functions | |
478 || node->no_reorder) | |
479 && !node->cpp_implicit_alias | |
480 && !DECL_DISREGARD_INLINE_LIMITS (decl) | |
481 && !DECL_DECLARED_INLINE_P (decl) | |
482 && !(DECL_CONTEXT (decl) | |
483 && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)) | |
484 && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl)) | |
485 node->force_output = 1; | |
0 | 486 |
487 /* If we've not yet emitted decl, tell the debug info about it. */ | |
488 if (!TREE_ASM_WRITTEN (decl)) | |
489 (*debug_hooks->deferred_inline_function) (decl); | |
490 | |
111 | 491 if (!no_collect) |
0 | 492 ggc_collect (); |
111 | 493 |
494 if (symtab->state == CONSTRUCTION | |
495 && (node->needed_p () || node->referred_to_p ())) | |
496 enqueue_node (node); | |
0 | 497 } |
498 | |
111 | 499 /* Add the function FNDECL to the call graph. |
500 Unlike finalize_function, this function is intended to be used | |
501 by middle end and allows insertion of new function at arbitrary point | |
502 of compilation. The function can be either in high, low or SSA form | |
503 GIMPLE. | |
504 | |
505 The function is assumed to be reachable and have address taken (so no | |
506 API breaking optimizations are performed on it). | |
507 | |
508 Main work done by this function is to enqueue the function for later | |
509 processing to avoid need the passes to be re-entrant. */ | |
0 | 510 |
511 void | |
111 | 512 cgraph_node::add_new_function (tree fndecl, bool lowered) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
513 { |
111 | 514 gcc::pass_manager *passes = g->get_passes (); |
515 cgraph_node *node; | |
516 | |
517 if (dump_file) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
518 { |
111 | 519 struct function *fn = DECL_STRUCT_FUNCTION (fndecl); |
520 const char *function_type = ((gimple_has_body_p (fndecl)) | |
521 ? (lowered | |
522 ? (gimple_in_ssa_p (fn) | |
523 ? "ssa gimple" | |
524 : "low gimple") | |
525 : "high gimple") | |
526 : "to-be-gimplified"); | |
527 fprintf (dump_file, | |
528 "Added new %s function %s to callgraph\n", | |
529 function_type, | |
530 fndecl_name (fndecl)); | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
531 } |
111 | 532 |
533 switch (symtab->state) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
534 { |
111 | 535 case PARSING: |
536 cgraph_node::finalize_function (fndecl, false); | |
537 break; | |
538 case CONSTRUCTION: | |
539 /* Just enqueue function to be processed at nearest occurrence. */ | |
540 node = cgraph_node::get_create (fndecl); | |
541 if (lowered) | |
542 node->lowered = true; | |
543 cgraph_new_nodes.safe_push (node); | |
544 break; | |
545 | |
546 case IPA: | |
547 case IPA_SSA: | |
548 case IPA_SSA_AFTER_INLINING: | |
549 case EXPANSION: | |
550 /* Bring the function into finalized state and enqueue for later | |
551 analyzing and compilation. */ | |
552 node = cgraph_node::get_create (fndecl); | |
553 node->local.local = false; | |
554 node->definition = true; | |
555 node->force_output = true; | |
556 if (TREE_PUBLIC (fndecl)) | |
557 node->externally_visible = true; | |
558 if (!lowered && symtab->state == EXPANSION) | |
559 { | |
560 push_cfun (DECL_STRUCT_FUNCTION (fndecl)); | |
561 gimple_register_cfg_hooks (); | |
562 bitmap_obstack_initialize (NULL); | |
563 execute_pass_list (cfun, passes->all_lowering_passes); | |
564 passes->execute_early_local_passes (); | |
565 bitmap_obstack_release (NULL); | |
566 pop_cfun (); | |
567 | |
568 lowered = true; | |
569 } | |
570 if (lowered) | |
571 node->lowered = true; | |
572 cgraph_new_nodes.safe_push (node); | |
573 break; | |
574 | |
575 case FINISHED: | |
576 /* At the very end of compilation we have to do all the work up | |
577 to expansion. */ | |
578 node = cgraph_node::create (fndecl); | |
579 if (lowered) | |
580 node->lowered = true; | |
581 node->definition = true; | |
582 node->analyze (); | |
583 push_cfun (DECL_STRUCT_FUNCTION (fndecl)); | |
584 gimple_register_cfg_hooks (); | |
585 bitmap_obstack_initialize (NULL); | |
586 if (!gimple_in_ssa_p (DECL_STRUCT_FUNCTION (fndecl))) | |
587 g->get_passes ()->execute_early_local_passes (); | |
588 bitmap_obstack_release (NULL); | |
589 pop_cfun (); | |
590 node->expand (); | |
591 break; | |
592 | |
593 default: | |
594 gcc_unreachable (); | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
595 } |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
596 |
111 | 597 /* Set a personality if required and we already passed EH lowering. */ |
598 if (lowered | |
599 && (function_needs_eh_personality (DECL_STRUCT_FUNCTION (fndecl)) | |
600 == eh_personality_lang)) | |
601 DECL_FUNCTION_PERSONALITY (fndecl) = lang_hooks.eh_personality (); | |
0 | 602 } |
603 | |
604 /* Analyze the function scheduled to be output. */ | |
111 | 605 void |
606 cgraph_node::analyze (void) | |
0 | 607 { |
111 | 608 if (native_rtl_p ()) |
609 { | |
610 analyzed = true; | |
611 return; | |
612 } | |
613 | |
614 tree decl = this->decl; | |
615 location_t saved_loc = input_location; | |
616 input_location = DECL_SOURCE_LOCATION (decl); | |
617 | |
618 if (thunk.thunk_p) | |
619 { | |
620 cgraph_node *t = cgraph_node::get (thunk.alias); | |
621 | |
131 | 622 create_edge (t, NULL, t->count); |
111 | 623 callees->can_throw_external = !TREE_NOTHROW (t->decl); |
624 /* Target code in expand_thunk may need the thunk's target | |
625 to be analyzed, so recurse here. */ | |
131 | 626 if (!t->analyzed && t->definition) |
111 | 627 t->analyze (); |
628 if (t->alias) | |
629 { | |
630 t = t->get_alias_target (); | |
131 | 631 if (!t->analyzed && t->definition) |
111 | 632 t->analyze (); |
633 } | |
131 | 634 bool ret = expand_thunk (false, false); |
111 | 635 thunk.alias = NULL; |
131 | 636 if (!ret) |
637 return; | |
111 | 638 } |
639 if (alias) | |
640 resolve_alias (cgraph_node::get (alias_target), transparent_alias); | |
641 else if (dispatcher_function) | |
642 { | |
643 /* Generate the dispatcher body of multi-versioned functions. */ | |
644 cgraph_function_version_info *dispatcher_version_info | |
645 = function_version (); | |
646 if (dispatcher_version_info != NULL | |
647 && (dispatcher_version_info->dispatcher_resolver | |
648 == NULL_TREE)) | |
649 { | |
650 tree resolver = NULL_TREE; | |
651 gcc_assert (targetm.generate_version_dispatcher_body); | |
652 resolver = targetm.generate_version_dispatcher_body (this); | |
653 gcc_assert (resolver != NULL_TREE); | |
654 } | |
655 } | |
656 else | |
657 { | |
658 push_cfun (DECL_STRUCT_FUNCTION (decl)); | |
659 | |
660 assign_assembler_name_if_needed (decl); | |
661 | |
662 /* Make sure to gimplify bodies only once. During analyzing a | |
663 function we lower it, which will require gimplified nested | |
664 functions, so we can end up here with an already gimplified | |
665 body. */ | |
666 if (!gimple_has_body_p (decl)) | |
667 gimplify_function_tree (decl); | |
668 | |
669 /* Lower the function. */ | |
670 if (!lowered) | |
671 { | |
672 if (nested) | |
673 lower_nested_functions (decl); | |
674 gcc_assert (!nested); | |
675 | |
676 gimple_register_cfg_hooks (); | |
677 bitmap_obstack_initialize (NULL); | |
678 execute_pass_list (cfun, g->get_passes ()->all_lowering_passes); | |
679 free_dominance_info (CDI_POST_DOMINATORS); | |
680 free_dominance_info (CDI_DOMINATORS); | |
681 compact_blocks (); | |
682 bitmap_obstack_release (NULL); | |
683 lowered = true; | |
684 } | |
685 | |
686 pop_cfun (); | |
687 } | |
688 analyzed = true; | |
689 | |
690 input_location = saved_loc; | |
691 } | |
692 | |
693 /* C++ frontend produce same body aliases all over the place, even before PCH | |
694 gets streamed out. It relies on us linking the aliases with their function | |
695 in order to do the fixups, but ipa-ref is not PCH safe. Consequentely we | |
696 first produce aliases without links, but once C++ FE is sure he won't sream | |
697 PCH we build the links via this function. */ | |
698 | |
699 void | |
700 symbol_table::process_same_body_aliases (void) | |
701 { | |
702 symtab_node *node; | |
703 FOR_EACH_SYMBOL (node) | |
704 if (node->cpp_implicit_alias && !node->analyzed) | |
705 node->resolve_alias | |
706 (VAR_P (node->alias_target) | |
707 ? (symtab_node *)varpool_node::get_create (node->alias_target) | |
708 : (symtab_node *)cgraph_node::get_create (node->alias_target)); | |
709 cpp_implicit_aliases_done = true; | |
0 | 710 } |
711 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
712 /* Process attributes common for vars and functions. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
713 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
714 static void |
111 | 715 process_common_attributes (symtab_node *node, tree decl) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
716 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
717 tree weakref = lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
718 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
719 if (weakref && !lookup_attribute ("alias", DECL_ATTRIBUTES (decl))) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
720 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
721 warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
722 "%<weakref%> attribute should be accompanied with" |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
723 " an %<alias%> attribute"); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
724 DECL_WEAK (decl) = 0; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
725 DECL_ATTRIBUTES (decl) = remove_attribute ("weakref", |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
726 DECL_ATTRIBUTES (decl)); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
727 } |
111 | 728 |
729 if (lookup_attribute ("no_reorder", DECL_ATTRIBUTES (decl))) | |
730 node->no_reorder = 1; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
731 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
732 |
0 | 733 /* Look for externally_visible and used attributes and mark cgraph nodes |
734 accordingly. | |
735 | |
736 We cannot mark the nodes at the point the attributes are processed (in | |
737 handle_*_attribute) because the copy of the declarations available at that | |
738 point may not be canonical. For example, in: | |
739 | |
740 void f(); | |
741 void f() __attribute__((used)); | |
742 | |
743 the declaration we see in handle_used_attribute will be the second | |
744 declaration -- but the front end will subsequently merge that declaration | |
745 with the original declaration and discard the second declaration. | |
746 | |
111 | 747 Furthermore, we can't mark these nodes in finalize_function because: |
0 | 748 |
749 void f() {} | |
750 void f() __attribute__((externally_visible)); | |
751 | |
752 is valid. | |
753 | |
754 So, we walk the nodes at the end of the translation unit, applying the | |
755 attributes at that point. */ | |
756 | |
757 static void | |
111 | 758 process_function_and_variable_attributes (cgraph_node *first, |
759 varpool_node *first_var) | |
0 | 760 { |
111 | 761 cgraph_node *node; |
762 varpool_node *vnode; | |
763 | |
764 for (node = symtab->first_function (); node != first; | |
765 node = symtab->next_function (node)) | |
0 | 766 { |
767 tree decl = node->decl; | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
768 if (DECL_PRESERVE_P (decl)) |
111 | 769 node->mark_force_output (); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
770 else if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl))) |
0 | 771 { |
772 if (! TREE_PUBLIC (node->decl)) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
773 warning_at (DECL_SOURCE_LOCATION (node->decl), OPT_Wattributes, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
774 "%<externally_visible%>" |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
775 " attribute have effect only on public objects"); |
0 | 776 } |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
777 if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)) |
111 | 778 && (node->definition && !node->alias)) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
779 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
780 warning_at (DECL_SOURCE_LOCATION (node->decl), OPT_Wattributes, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
781 "%<weakref%> attribute ignored" |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
782 " because function is defined"); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
783 DECL_WEAK (decl) = 0; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
784 DECL_ATTRIBUTES (decl) = remove_attribute ("weakref", |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
785 DECL_ATTRIBUTES (decl)); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
786 } |
131 | 787 else if (lookup_attribute ("alias", DECL_ATTRIBUTES (decl)) |
788 && node->definition | |
789 && !node->alias) | |
790 warning_at (DECL_SOURCE_LOCATION (node->decl), OPT_Wattributes, | |
791 "%<alias%> attribute ignored" | |
792 " because function is defined"); | |
111 | 793 |
794 if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (decl)) | |
795 && !DECL_DECLARED_INLINE_P (decl) | |
796 /* redefining extern inline function makes it DECL_UNINLINABLE. */ | |
797 && !DECL_UNINLINABLE (decl)) | |
798 warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes, | |
799 "always_inline function might not be inlinable"); | |
800 | |
801 process_common_attributes (node, decl); | |
0 | 802 } |
111 | 803 for (vnode = symtab->first_variable (); vnode != first_var; |
804 vnode = symtab->next_variable (vnode)) | |
0 | 805 { |
806 tree decl = vnode->decl; | |
111 | 807 if (DECL_EXTERNAL (decl) |
808 && DECL_INITIAL (decl)) | |
809 varpool_node::finalize_decl (decl); | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
810 if (DECL_PRESERVE_P (decl)) |
111 | 811 vnode->force_output = true; |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
812 else if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl))) |
0 | 813 { |
814 if (! TREE_PUBLIC (vnode->decl)) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
815 warning_at (DECL_SOURCE_LOCATION (vnode->decl), OPT_Wattributes, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
816 "%<externally_visible%>" |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
817 " attribute have effect only on public objects"); |
0 | 818 } |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
819 if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)) |
111 | 820 && vnode->definition |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
821 && DECL_INITIAL (decl)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
822 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
823 warning_at (DECL_SOURCE_LOCATION (vnode->decl), OPT_Wattributes, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
824 "%<weakref%> attribute ignored" |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
825 " because variable is initialized"); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
826 DECL_WEAK (decl) = 0; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
827 DECL_ATTRIBUTES (decl) = remove_attribute ("weakref", |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
828 DECL_ATTRIBUTES (decl)); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
829 } |
111 | 830 process_common_attributes (vnode, decl); |
0 | 831 } |
832 } | |
833 | |
111 | 834 /* Mark DECL as finalized. By finalizing the declaration, frontend instruct the |
835 middle end to output the variable to asm file, if needed or externally | |
836 visible. */ | |
837 | |
838 void | |
839 varpool_node::finalize_decl (tree decl) | |
840 { | |
841 varpool_node *node = varpool_node::get_create (decl); | |
842 | |
843 gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl)); | |
844 | |
845 if (node->definition) | |
846 return; | |
847 /* Set definition first before calling notice_global_symbol so that | |
848 it is available to notice_global_symbol. */ | |
849 node->definition = true; | |
850 notice_global_symbol (decl); | |
851 if (!flag_toplevel_reorder) | |
852 node->no_reorder = true; | |
853 if (TREE_THIS_VOLATILE (decl) || DECL_PRESERVE_P (decl) | |
854 /* Traditionally we do not eliminate static variables when not | |
855 optimizing and when not doing toplevel reoder. */ | |
856 || (node->no_reorder && !DECL_COMDAT (node->decl) | |
857 && !DECL_ARTIFICIAL (node->decl))) | |
858 node->force_output = true; | |
859 | |
860 if (symtab->state == CONSTRUCTION | |
861 && (node->needed_p () || node->referred_to_p ())) | |
862 enqueue_node (node); | |
863 if (symtab->state >= IPA_SSA) | |
864 node->analyze (); | |
865 /* Some frontends produce various interface variables after compilation | |
866 finished. */ | |
867 if (symtab->state == FINISHED | |
868 || (node->no_reorder | |
869 && symtab->state == EXPANSION)) | |
870 node->assemble_decl (); | |
871 } | |
872 | |
873 /* EDGE is an polymorphic call. Mark all possible targets as reachable | |
874 and if there is only one target, perform trivial devirtualization. | |
875 REACHABLE_CALL_TARGETS collects target lists we already walked to | |
876 avoid udplicate work. */ | |
0 | 877 |
878 static void | |
111 | 879 walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets, |
880 cgraph_edge *edge) | |
881 { | |
882 unsigned int i; | |
883 void *cache_token; | |
884 bool final; | |
885 vec <cgraph_node *>targets | |
886 = possible_polymorphic_call_targets | |
887 (edge, &final, &cache_token); | |
888 | |
889 if (!reachable_call_targets->add (cache_token)) | |
890 { | |
891 if (symtab->dump_file) | |
892 dump_possible_polymorphic_call_targets | |
893 (symtab->dump_file, edge); | |
894 | |
895 for (i = 0; i < targets.length (); i++) | |
896 { | |
897 /* Do not bother to mark virtual methods in anonymous namespace; | |
898 either we will find use of virtual table defining it, or it is | |
899 unused. */ | |
900 if (targets[i]->definition | |
901 && TREE_CODE | |
902 (TREE_TYPE (targets[i]->decl)) | |
903 == METHOD_TYPE | |
904 && !type_in_anonymous_namespace_p | |
905 (TYPE_METHOD_BASETYPE (TREE_TYPE (targets[i]->decl)))) | |
906 enqueue_node (targets[i]); | |
907 } | |
908 } | |
909 | |
910 /* Very trivial devirtualization; when the type is | |
911 final or anonymous (so we know all its derivation) | |
912 and there is only one possible virtual call target, | |
913 make the edge direct. */ | |
914 if (final) | |
915 { | |
916 if (targets.length () <= 1 && dbg_cnt (devirt)) | |
917 { | |
918 cgraph_node *target; | |
919 if (targets.length () == 1) | |
920 target = targets[0]; | |
921 else | |
922 target = cgraph_node::create | |
923 (builtin_decl_implicit (BUILT_IN_UNREACHABLE)); | |
924 | |
925 if (symtab->dump_file) | |
926 { | |
927 fprintf (symtab->dump_file, | |
928 "Devirtualizing call: "); | |
929 print_gimple_stmt (symtab->dump_file, | |
930 edge->call_stmt, 0, | |
931 TDF_SLIM); | |
932 } | |
933 if (dump_enabled_p ()) | |
934 { | |
131 | 935 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, edge->call_stmt, |
111 | 936 "devirtualizing call in %s to %s\n", |
937 edge->caller->name (), target->name ()); | |
938 } | |
939 | |
940 edge->make_direct (target); | |
941 edge->redirect_call_stmt_to_callee (); | |
942 | |
943 if (symtab->dump_file) | |
944 { | |
945 fprintf (symtab->dump_file, | |
946 "Devirtualized as: "); | |
947 print_gimple_stmt (symtab->dump_file, | |
948 edge->call_stmt, 0, | |
949 TDF_SLIM); | |
950 } | |
951 } | |
952 } | |
953 } | |
954 | |
955 /* Issue appropriate warnings for the global declaration DECL. */ | |
956 | |
957 static void | |
958 check_global_declaration (symtab_node *snode) | |
959 { | |
960 const char *decl_file; | |
961 tree decl = snode->decl; | |
962 | |
963 /* Warn about any function declared static but not defined. We don't | |
964 warn about variables, because many programs have static variables | |
965 that exist only to get some text into the object file. */ | |
966 if (TREE_CODE (decl) == FUNCTION_DECL | |
967 && DECL_INITIAL (decl) == 0 | |
968 && DECL_EXTERNAL (decl) | |
969 && ! DECL_ARTIFICIAL (decl) | |
970 && ! TREE_NO_WARNING (decl) | |
971 && ! TREE_PUBLIC (decl) | |
972 && (warn_unused_function | |
973 || snode->referred_to_p (/*include_self=*/false))) | |
974 { | |
975 if (snode->referred_to_p (/*include_self=*/false)) | |
976 pedwarn (input_location, 0, "%q+F used but never defined", decl); | |
977 else | |
978 warning (OPT_Wunused_function, "%q+F declared %<static%> but never defined", decl); | |
979 /* This symbol is effectively an "extern" declaration now. */ | |
980 TREE_PUBLIC (decl) = 1; | |
981 } | |
982 | |
983 /* Warn about static fns or vars defined but not used. */ | |
984 if (((warn_unused_function && TREE_CODE (decl) == FUNCTION_DECL) | |
985 || (((warn_unused_variable && ! TREE_READONLY (decl)) | |
986 || (warn_unused_const_variable > 0 && TREE_READONLY (decl) | |
987 && (warn_unused_const_variable == 2 | |
988 || (main_input_filename != NULL | |
989 && (decl_file = DECL_SOURCE_FILE (decl)) != NULL | |
990 && filename_cmp (main_input_filename, | |
991 decl_file) == 0)))) | |
992 && VAR_P (decl))) | |
993 && ! DECL_IN_SYSTEM_HEADER (decl) | |
994 && ! snode->referred_to_p (/*include_self=*/false) | |
995 /* This TREE_USED check is needed in addition to referred_to_p | |
996 above, because the `__unused__' attribute is not being | |
997 considered for referred_to_p. */ | |
998 && ! TREE_USED (decl) | |
999 /* The TREE_USED bit for file-scope decls is kept in the identifier, | |
1000 to handle multiple external decls in different scopes. */ | |
1001 && ! (DECL_NAME (decl) && TREE_USED (DECL_NAME (decl))) | |
1002 && ! DECL_EXTERNAL (decl) | |
1003 && ! DECL_ARTIFICIAL (decl) | |
1004 && ! DECL_ABSTRACT_ORIGIN (decl) | |
1005 && ! TREE_PUBLIC (decl) | |
1006 /* A volatile variable might be used in some non-obvious way. */ | |
1007 && (! VAR_P (decl) || ! TREE_THIS_VOLATILE (decl)) | |
1008 /* Global register variables must be declared to reserve them. */ | |
1009 && ! (VAR_P (decl) && DECL_REGISTER (decl)) | |
1010 /* Global ctors and dtors are called by the runtime. */ | |
1011 && (TREE_CODE (decl) != FUNCTION_DECL | |
1012 || (!DECL_STATIC_CONSTRUCTOR (decl) | |
1013 && !DECL_STATIC_DESTRUCTOR (decl))) | |
1014 /* Otherwise, ask the language. */ | |
1015 && lang_hooks.decls.warn_unused_global (decl)) | |
1016 warning_at (DECL_SOURCE_LOCATION (decl), | |
1017 (TREE_CODE (decl) == FUNCTION_DECL) | |
1018 ? OPT_Wunused_function | |
1019 : (TREE_READONLY (decl) | |
1020 ? OPT_Wunused_const_variable_ | |
1021 : OPT_Wunused_variable), | |
1022 "%qD defined but not used", decl); | |
1023 } | |
1024 | |
1025 /* Discover all functions and variables that are trivially needed, analyze | |
1026 them as well as all functions and variables referred by them */ | |
1027 static cgraph_node *first_analyzed; | |
1028 static varpool_node *first_analyzed_var; | |
1029 | |
1030 /* FIRST_TIME is set to TRUE for the first time we are called for a | |
1031 translation unit from finalize_compilation_unit() or false | |
1032 otherwise. */ | |
1033 | |
1034 static void | |
1035 analyze_functions (bool first_time) | |
0 | 1036 { |
1037 /* Keep track of already processed nodes when called multiple times for | |
1038 intermodule optimization. */ | |
111 | 1039 cgraph_node *first_handled = first_analyzed; |
1040 varpool_node *first_handled_var = first_analyzed_var; | |
1041 hash_set<void *> reachable_call_targets; | |
1042 | |
1043 symtab_node *node; | |
1044 symtab_node *next; | |
1045 int i; | |
1046 ipa_ref *ref; | |
1047 bool changed = true; | |
1048 location_t saved_loc = input_location; | |
0 | 1049 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1050 bitmap_obstack_initialize (NULL); |
111 | 1051 symtab->state = CONSTRUCTION; |
1052 input_location = UNKNOWN_LOCATION; | |
1053 | |
1054 /* Ugly, but the fixup can not happen at a time same body alias is created; | |
1055 C++ FE is confused about the COMDAT groups being right. */ | |
1056 if (symtab->cpp_implicit_aliases_done) | |
1057 FOR_EACH_SYMBOL (node) | |
1058 if (node->cpp_implicit_alias) | |
1059 node->fixup_same_cpp_alias_visibility (node->get_alias_target ()); | |
1060 build_type_inheritance_graph (); | |
1061 | |
1062 /* Analysis adds static variables that in turn adds references to new functions. | |
1063 So we need to iterate the process until it stabilize. */ | |
1064 while (changed) | |
0 | 1065 { |
111 | 1066 changed = false; |
1067 process_function_and_variable_attributes (first_analyzed, | |
1068 first_analyzed_var); | |
1069 | |
1070 /* First identify the trivially needed symbols. */ | |
1071 for (node = symtab->first_symbol (); | |
1072 node != first_analyzed | |
1073 && node != first_analyzed_var; node = node->next) | |
1074 { | |
1075 /* Convert COMDAT group designators to IDENTIFIER_NODEs. */ | |
1076 node->get_comdat_group_id (); | |
1077 if (node->needed_p ()) | |
1078 { | |
1079 enqueue_node (node); | |
1080 if (!changed && symtab->dump_file) | |
1081 fprintf (symtab->dump_file, "Trivially needed symbols:"); | |
1082 changed = true; | |
1083 if (symtab->dump_file) | |
1084 fprintf (symtab->dump_file, " %s", node->asm_name ()); | |
1085 if (!changed && symtab->dump_file) | |
1086 fprintf (symtab->dump_file, "\n"); | |
1087 } | |
1088 if (node == first_analyzed | |
1089 || node == first_analyzed_var) | |
1090 break; | |
1091 } | |
1092 symtab->process_new_functions (); | |
1093 first_analyzed_var = symtab->first_variable (); | |
1094 first_analyzed = symtab->first_function (); | |
1095 | |
1096 if (changed && symtab->dump_file) | |
1097 fprintf (symtab->dump_file, "\n"); | |
1098 | |
1099 /* Lower representation, build callgraph edges and references for all trivially | |
1100 needed symbols and all symbols referred by them. */ | |
1101 while (queued_nodes != &symtab_terminator) | |
0 | 1102 { |
111 | 1103 changed = true; |
1104 node = queued_nodes; | |
1105 queued_nodes = (symtab_node *)queued_nodes->aux; | |
1106 cgraph_node *cnode = dyn_cast <cgraph_node *> (node); | |
1107 if (cnode && cnode->definition) | |
1108 { | |
1109 cgraph_edge *edge; | |
1110 tree decl = cnode->decl; | |
1111 | |
1112 /* ??? It is possible to create extern inline function | |
1113 and later using weak alias attribute to kill its body. | |
1114 See gcc.c-torture/compile/20011119-1.c */ | |
1115 if (!DECL_STRUCT_FUNCTION (decl) | |
1116 && !cnode->alias | |
1117 && !cnode->thunk.thunk_p | |
1118 && !cnode->dispatcher_function) | |
1119 { | |
1120 cnode->reset (); | |
1121 cnode->local.redefined_extern_inline = true; | |
1122 continue; | |
1123 } | |
1124 | |
1125 if (!cnode->analyzed) | |
1126 cnode->analyze (); | |
1127 | |
1128 for (edge = cnode->callees; edge; edge = edge->next_callee) | |
1129 if (edge->callee->definition | |
1130 && (!DECL_EXTERNAL (edge->callee->decl) | |
1131 /* When not optimizing, do not try to analyze extern | |
1132 inline functions. Doing so is pointless. */ | |
1133 || opt_for_fn (edge->callee->decl, optimize) | |
1134 /* Weakrefs needs to be preserved. */ | |
1135 || edge->callee->alias | |
1136 /* always_inline functions are inlined aven at -O0. */ | |
1137 || lookup_attribute | |
1138 ("always_inline", | |
1139 DECL_ATTRIBUTES (edge->callee->decl)) | |
1140 /* Multiversioned functions needs the dispatcher to | |
1141 be produced locally even for extern functions. */ | |
1142 || edge->callee->function_version ())) | |
1143 enqueue_node (edge->callee); | |
1144 if (opt_for_fn (cnode->decl, optimize) | |
1145 && opt_for_fn (cnode->decl, flag_devirtualize)) | |
1146 { | |
1147 cgraph_edge *next; | |
1148 | |
1149 for (edge = cnode->indirect_calls; edge; edge = next) | |
1150 { | |
1151 next = edge->next_callee; | |
1152 if (edge->indirect_info->polymorphic) | |
1153 walk_polymorphic_call_targets (&reachable_call_targets, | |
1154 edge); | |
1155 } | |
1156 } | |
1157 | |
1158 /* If decl is a clone of an abstract function, | |
1159 mark that abstract function so that we don't release its body. | |
1160 The DECL_INITIAL() of that abstract function declaration | |
1161 will be later needed to output debug info. */ | |
1162 if (DECL_ABSTRACT_ORIGIN (decl)) | |
1163 { | |
1164 cgraph_node *origin_node | |
1165 = cgraph_node::get_create (DECL_ABSTRACT_ORIGIN (decl)); | |
1166 origin_node->used_as_abstract_origin = true; | |
1167 } | |
1168 /* Preserve a functions function context node. It will | |
1169 later be needed to output debug info. */ | |
1170 if (tree fn = decl_function_context (decl)) | |
1171 { | |
1172 cgraph_node *origin_node = cgraph_node::get_create (fn); | |
1173 enqueue_node (origin_node); | |
1174 } | |
1175 } | |
1176 else | |
1177 { | |
1178 varpool_node *vnode = dyn_cast <varpool_node *> (node); | |
1179 if (vnode && vnode->definition && !vnode->analyzed) | |
1180 vnode->analyze (); | |
1181 } | |
1182 | |
1183 if (node->same_comdat_group) | |
1184 { | |
1185 symtab_node *next; | |
1186 for (next = node->same_comdat_group; | |
1187 next != node; | |
1188 next = next->same_comdat_group) | |
1189 if (!next->comdat_local_p ()) | |
1190 enqueue_node (next); | |
1191 } | |
1192 for (i = 0; node->iterate_reference (i, ref); i++) | |
1193 if (ref->referred->definition | |
1194 && (!DECL_EXTERNAL (ref->referred->decl) | |
1195 || ((TREE_CODE (ref->referred->decl) != FUNCTION_DECL | |
1196 && optimize) | |
1197 || (TREE_CODE (ref->referred->decl) == FUNCTION_DECL | |
1198 && opt_for_fn (ref->referred->decl, optimize)) | |
1199 || node->alias | |
1200 || ref->referred->alias))) | |
1201 enqueue_node (ref->referred); | |
1202 symtab->process_new_functions (); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1203 } |
0 | 1204 } |
111 | 1205 update_type_inheritance_graph (); |
0 | 1206 |
1207 /* Collect entry points to the unit. */ | |
111 | 1208 if (symtab->dump_file) |
0 | 1209 { |
111 | 1210 fprintf (symtab->dump_file, "\n\nInitial "); |
1211 symtab->dump (symtab->dump_file); | |
1212 } | |
1213 | |
1214 if (first_time) | |
1215 { | |
1216 symtab_node *snode; | |
1217 FOR_EACH_SYMBOL (snode) | |
1218 check_global_declaration (snode); | |
0 | 1219 } |
1220 | |
111 | 1221 if (symtab->dump_file) |
1222 fprintf (symtab->dump_file, "\nRemoving unused symbols:"); | |
1223 | |
1224 for (node = symtab->first_symbol (); | |
1225 node != first_handled | |
1226 && node != first_handled_var; node = next) | |
0 | 1227 { |
1228 next = node->next; | |
111 | 1229 if (!node->aux && !node->referred_to_p ()) |
0 | 1230 { |
111 | 1231 if (symtab->dump_file) |
1232 fprintf (symtab->dump_file, " %s", node->name ()); | |
1233 | |
1234 /* See if the debugger can use anything before the DECL | |
1235 passes away. Perhaps it can notice a DECL that is now a | |
1236 constant and can tag the early DIE with an appropriate | |
1237 attribute. | |
1238 | |
1239 Otherwise, this is the last chance the debug_hooks have | |
1240 at looking at optimized away DECLs, since | |
1241 late_global_decl will subsequently be called from the | |
1242 contents of the now pruned symbol table. */ | |
1243 if (VAR_P (node->decl) | |
1244 && !decl_function_context (node->decl)) | |
1245 { | |
1246 /* We are reclaiming totally unreachable code and variables | |
1247 so they effectively appear as readonly. Show that to | |
1248 the debug machinery. */ | |
1249 TREE_READONLY (node->decl) = 1; | |
1250 node->definition = false; | |
1251 (*debug_hooks->late_global_decl) (node->decl); | |
1252 } | |
1253 | |
1254 node->remove (); | |
0 | 1255 continue; |
1256 } | |
111 | 1257 if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node)) |
1258 { | |
1259 tree decl = node->decl; | |
1260 | |
1261 if (cnode->definition && !gimple_has_body_p (decl) | |
1262 && !cnode->alias | |
1263 && !cnode->thunk.thunk_p) | |
1264 cnode->reset (); | |
1265 | |
1266 gcc_assert (!cnode->definition || cnode->thunk.thunk_p | |
1267 || cnode->alias | |
1268 || gimple_has_body_p (decl) | |
1269 || cnode->native_rtl_p ()); | |
1270 gcc_assert (cnode->analyzed == cnode->definition); | |
1271 } | |
1272 node->aux = NULL; | |
0 | 1273 } |
111 | 1274 for (;node; node = node->next) |
1275 node->aux = NULL; | |
1276 first_analyzed = symtab->first_function (); | |
1277 first_analyzed_var = symtab->first_variable (); | |
1278 if (symtab->dump_file) | |
0 | 1279 { |
111 | 1280 fprintf (symtab->dump_file, "\n\nReclaimed "); |
1281 symtab->dump (symtab->dump_file); | |
0 | 1282 } |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1283 bitmap_obstack_release (NULL); |
0 | 1284 ggc_collect (); |
111 | 1285 /* Initialize assembler name hash, in particular we want to trigger C++ |
1286 mangling and same body alias creation before we free DECL_ARGUMENTS | |
1287 used by it. */ | |
1288 if (!seen_error ()) | |
1289 symtab->symtab_initialize_asm_name_hash (); | |
1290 | |
1291 input_location = saved_loc; | |
0 | 1292 } |
1293 | |
111 | 1294 /* Check declaration of the type of ALIAS for compatibility with its TARGET |
1295 (which may be an ifunc resolver) and issue a diagnostic when they are | |
1296 not compatible according to language rules (plus a C++ extension for | |
1297 non-static member functions). */ | |
1298 | |
1299 static void | |
1300 maybe_diag_incompatible_alias (tree alias, tree target) | |
0 | 1301 { |
111 | 1302 tree altype = TREE_TYPE (alias); |
1303 tree targtype = TREE_TYPE (target); | |
1304 | |
131 | 1305 bool ifunc = cgraph_node::get (alias)->ifunc_resolver; |
111 | 1306 tree funcptr = altype; |
1307 | |
1308 if (ifunc) | |
0 | 1309 { |
111 | 1310 /* Handle attribute ifunc first. */ |
1311 if (TREE_CODE (altype) == METHOD_TYPE) | |
1312 { | |
1313 /* Set FUNCPTR to the type of the alias target. If the type | |
1314 is a non-static member function of class C, construct a type | |
1315 of an ordinary function taking C* as the first argument, | |
1316 followed by the member function argument list, and use it | |
1317 instead to check for incompatibility. This conversion is | |
1318 not defined by the language but an extension provided by | |
1319 G++. */ | |
1320 | |
1321 tree rettype = TREE_TYPE (altype); | |
1322 tree args = TYPE_ARG_TYPES (altype); | |
1323 altype = build_function_type (rettype, args); | |
1324 funcptr = altype; | |
1325 } | |
1326 | |
1327 targtype = TREE_TYPE (targtype); | |
1328 | |
1329 if (POINTER_TYPE_P (targtype)) | |
1330 { | |
1331 targtype = TREE_TYPE (targtype); | |
1332 | |
1333 /* Only issue Wattribute-alias for conversions to void* with | |
1334 -Wextra. */ | |
1335 if (VOID_TYPE_P (targtype) && !extra_warnings) | |
1336 return; | |
1337 | |
1338 /* Proceed to handle incompatible ifunc resolvers below. */ | |
1339 } | |
1340 else | |
1341 { | |
1342 funcptr = build_pointer_type (funcptr); | |
1343 | |
1344 error_at (DECL_SOURCE_LOCATION (target), | |
1345 "%<ifunc%> resolver for %qD must return %qT", | |
1346 alias, funcptr); | |
1347 inform (DECL_SOURCE_LOCATION (alias), | |
1348 "resolver indirect function declared here"); | |
1349 return; | |
1350 } | |
1351 } | |
1352 | |
1353 if ((!FUNC_OR_METHOD_TYPE_P (targtype) | |
1354 || (prototype_p (altype) | |
1355 && prototype_p (targtype) | |
1356 && !types_compatible_p (altype, targtype)))) | |
1357 { | |
1358 /* Warn for incompatibilities. Avoid warning for functions | |
1359 without a prototype to make it possible to declare aliases | |
1360 without knowing the exact type, as libstdc++ does. */ | |
1361 if (ifunc) | |
1362 { | |
1363 funcptr = build_pointer_type (funcptr); | |
1364 | |
131 | 1365 auto_diagnostic_group d; |
111 | 1366 if (warning_at (DECL_SOURCE_LOCATION (target), |
1367 OPT_Wattribute_alias, | |
1368 "%<ifunc%> resolver for %qD should return %qT", | |
1369 alias, funcptr)) | |
1370 inform (DECL_SOURCE_LOCATION (alias), | |
1371 "resolver indirect function declared here"); | |
1372 } | |
131 | 1373 else |
1374 { | |
1375 auto_diagnostic_group d; | |
1376 if (warning_at (DECL_SOURCE_LOCATION (alias), | |
1377 OPT_Wattribute_alias, | |
1378 "%qD alias between functions of incompatible " | |
1379 "types %qT and %qT", alias, altype, targtype)) | |
1380 inform (DECL_SOURCE_LOCATION (target), | |
1381 "aliased declaration here"); | |
1382 } | |
0 | 1383 } |
111 | 1384 } |
1385 | |
1386 /* Translate the ugly representation of aliases as alias pairs into nice | |
1387 representation in callgraph. We don't handle all cases yet, | |
1388 unfortunately. */ | |
1389 | |
1390 static void | |
1391 handle_alias_pairs (void) | |
1392 { | |
1393 alias_pair *p; | |
1394 unsigned i; | |
1395 | |
1396 for (i = 0; alias_pairs && alias_pairs->iterate (i, &p);) | |
1397 { | |
1398 symtab_node *target_node = symtab_node::get_for_asmname (p->target); | |
1399 | |
1400 /* Weakrefs with target not defined in current unit are easy to handle: | |
1401 they behave just as external variables except we need to note the | |
1402 alias flag to later output the weakref pseudo op into asm file. */ | |
1403 if (!target_node | |
1404 && lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)) != NULL) | |
1405 { | |
1406 symtab_node *node = symtab_node::get (p->decl); | |
1407 if (node) | |
1408 { | |
1409 node->alias_target = p->target; | |
1410 node->weakref = true; | |
1411 node->alias = true; | |
1412 node->transparent_alias = true; | |
1413 } | |
1414 alias_pairs->unordered_remove (i); | |
1415 continue; | |
1416 } | |
1417 else if (!target_node) | |
1418 { | |
1419 error ("%q+D aliased to undefined symbol %qE", p->decl, p->target); | |
1420 symtab_node *node = symtab_node::get (p->decl); | |
1421 if (node) | |
1422 node->alias = false; | |
1423 alias_pairs->unordered_remove (i); | |
1424 continue; | |
1425 } | |
1426 | |
1427 if (DECL_EXTERNAL (target_node->decl) | |
1428 /* We use local aliases for C++ thunks to force the tailcall | |
1429 to bind locally. This is a hack - to keep it working do | |
1430 the following (which is not strictly correct). */ | |
1431 && (TREE_CODE (target_node->decl) != FUNCTION_DECL | |
1432 || ! DECL_VIRTUAL_P (target_node->decl)) | |
1433 && ! lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl))) | |
1434 { | |
1435 error ("%q+D aliased to external symbol %qE", | |
1436 p->decl, p->target); | |
1437 } | |
1438 | |
1439 if (TREE_CODE (p->decl) == FUNCTION_DECL | |
1440 && target_node && is_a <cgraph_node *> (target_node)) | |
1441 { | |
1442 maybe_diag_incompatible_alias (p->decl, target_node->decl); | |
1443 | |
1444 cgraph_node *src_node = cgraph_node::get (p->decl); | |
1445 if (src_node && src_node->definition) | |
1446 src_node->reset (); | |
1447 cgraph_node::create_alias (p->decl, target_node->decl); | |
1448 alias_pairs->unordered_remove (i); | |
1449 } | |
1450 else if (VAR_P (p->decl) | |
1451 && target_node && is_a <varpool_node *> (target_node)) | |
1452 { | |
1453 varpool_node::create_alias (p->decl, target_node->decl); | |
1454 alias_pairs->unordered_remove (i); | |
1455 } | |
1456 else | |
1457 { | |
1458 error ("%q+D alias between function and variable is not supported", | |
1459 p->decl); | |
1460 inform (DECL_SOURCE_LOCATION (target_node->decl), | |
1461 "aliased declaration here"); | |
1462 | |
1463 alias_pairs->unordered_remove (i); | |
1464 } | |
1465 } | |
1466 vec_free (alias_pairs); | |
0 | 1467 } |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1468 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1469 |
0 | 1470 /* Figure out what functions we want to assemble. */ |
1471 | |
1472 static void | |
111 | 1473 mark_functions_to_output (void) |
0 | 1474 { |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1475 bool check_same_comdat_groups = false; |
111 | 1476 cgraph_node *node; |
1477 | |
1478 if (flag_checking) | |
1479 FOR_EACH_FUNCTION (node) | |
1480 gcc_assert (!node->process); | |
1481 | |
1482 FOR_EACH_FUNCTION (node) | |
0 | 1483 { |
1484 tree decl = node->decl; | |
1485 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1486 gcc_assert (!node->process || node->same_comdat_group); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1487 if (node->process) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1488 continue; |
0 | 1489 |
1490 /* We need to output all local functions that are used and not | |
1491 always inlined, as well as those that are reachable from | |
1492 outside the current compilation unit. */ | |
1493 if (node->analyzed | |
111 | 1494 && !node->thunk.thunk_p |
1495 && !node->alias | |
0 | 1496 && !node->global.inlined_to |
1497 && !TREE_ASM_WRITTEN (decl) | |
1498 && !DECL_EXTERNAL (decl)) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1499 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1500 node->process = 1; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1501 if (node->same_comdat_group) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1502 { |
111 | 1503 cgraph_node *next; |
1504 for (next = dyn_cast<cgraph_node *> (node->same_comdat_group); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1505 next != node; |
111 | 1506 next = dyn_cast<cgraph_node *> (next->same_comdat_group)) |
1507 if (!next->thunk.thunk_p && !next->alias | |
1508 && !next->comdat_local_p ()) | |
1509 next->process = 1; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1510 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1511 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1512 else if (node->same_comdat_group) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1513 { |
111 | 1514 if (flag_checking) |
1515 check_same_comdat_groups = true; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1516 } |
0 | 1517 else |
1518 { | |
1519 /* We should've reclaimed all functions that are not needed. */ | |
111 | 1520 if (flag_checking |
1521 && !node->global.inlined_to | |
0 | 1522 && gimple_has_body_p (decl) |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1523 /* FIXME: in ltrans unit when offline copy is outside partition but inline copies |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1524 are inside partition, we can end up not removing the body since we no longer |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1525 have analyzed node pointing to it. */ |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1526 && !node->in_other_partition |
111 | 1527 && !node->alias |
1528 && !node->clones | |
0 | 1529 && !DECL_EXTERNAL (decl)) |
1530 { | |
111 | 1531 node->debug (); |
0 | 1532 internal_error ("failed to reclaim unneeded function"); |
1533 } | |
1534 gcc_assert (node->global.inlined_to | |
1535 || !gimple_has_body_p (decl) | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1536 || node->in_other_partition |
111 | 1537 || node->clones |
1538 || DECL_ARTIFICIAL (decl) | |
0 | 1539 || DECL_EXTERNAL (decl)); |
1540 | |
1541 } | |
1542 | |
1543 } | |
111 | 1544 if (flag_checking && check_same_comdat_groups) |
1545 FOR_EACH_FUNCTION (node) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1546 if (node->same_comdat_group && !node->process) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1547 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1548 tree decl = node->decl; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1549 if (!node->global.inlined_to |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1550 && gimple_has_body_p (decl) |
111 | 1551 /* FIXME: in an ltrans unit when the offline copy is outside a |
1552 partition but inline copies are inside a partition, we can | |
1553 end up not removing the body since we no longer have an | |
1554 analyzed node pointing to it. */ | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1555 && !node->in_other_partition |
111 | 1556 && !node->clones |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1557 && !DECL_EXTERNAL (decl)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1558 { |
111 | 1559 node->debug (); |
1560 internal_error ("failed to reclaim unneeded function in same " | |
1561 "comdat group"); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1562 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1563 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1564 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1565 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1566 /* DECL is FUNCTION_DECL. Initialize datastructures so DECL is a function |
111 | 1567 in lowered gimple form. IN_SSA is true if the gimple is in SSA. |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1568 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1569 Set current_function_decl and cfun to newly constructed empty function body. |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1570 return basic block in the function body. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1571 |
111 | 1572 basic_block |
1573 init_lowered_empty_function (tree decl, bool in_ssa, profile_count count) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1574 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1575 basic_block bb; |
111 | 1576 edge e; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1577 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1578 current_function_decl = decl; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1579 allocate_struct_function (decl, false); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1580 gimple_register_cfg_hooks (); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1581 init_empty_tree_cfg (); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1582 init_tree_ssa (cfun); |
111 | 1583 |
1584 if (in_ssa) | |
1585 { | |
1586 init_ssa_operands (cfun); | |
1587 cfun->gimple_df->in_ssa_p = true; | |
1588 cfun->curr_properties |= PROP_ssa; | |
1589 } | |
1590 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1591 DECL_INITIAL (decl) = make_node (BLOCK); |
111 | 1592 BLOCK_SUPERCONTEXT (DECL_INITIAL (decl)) = decl; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1593 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1594 DECL_SAVED_TREE (decl) = error_mark_node; |
111 | 1595 cfun->curr_properties |= (PROP_gimple_lcf | PROP_gimple_leh | PROP_gimple_any |
1596 | PROP_cfg | PROP_loops); | |
1597 | |
1598 set_loops_for_fn (cfun, ggc_cleared_alloc<loops> ()); | |
1599 init_loops_structure (cfun, loops_for_fn (cfun), 1); | |
1600 loops_for_fn (cfun)->state |= LOOPS_MAY_HAVE_MULTIPLE_LATCHES; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1601 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1602 /* Create BB for body of the function and connect it properly. */ |
111 | 1603 ENTRY_BLOCK_PTR_FOR_FN (cfun)->count = count; |
1604 EXIT_BLOCK_PTR_FOR_FN (cfun)->count = count; | |
1605 bb = create_basic_block (NULL, ENTRY_BLOCK_PTR_FOR_FN (cfun)); | |
1606 bb->count = count; | |
1607 e = make_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun), bb, EDGE_FALLTHRU); | |
1608 e->probability = profile_probability::always (); | |
1609 e = make_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0); | |
1610 e->probability = profile_probability::always (); | |
1611 add_bb_to_loop (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun)->loop_father); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1612 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1613 return bb; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1614 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1615 |
131 | 1616 /* Adjust PTR by the constant FIXED_OFFSET, by the vtable offset indicated by |
1617 VIRTUAL_OFFSET, and by the indirect offset indicated by INDIRECT_OFFSET, if | |
1618 it is non-null. THIS_ADJUSTING is nonzero for a this adjusting thunk and zero | |
1619 for a result adjusting thunk. */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1620 |
111 | 1621 tree |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1622 thunk_adjust (gimple_stmt_iterator * bsi, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1623 tree ptr, bool this_adjusting, |
131 | 1624 HOST_WIDE_INT fixed_offset, tree virtual_offset, |
1625 HOST_WIDE_INT indirect_offset) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1626 { |
111 | 1627 gassign *stmt; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1628 tree ret; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1629 |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1630 if (this_adjusting |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1631 && fixed_offset != 0) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1632 { |
111 | 1633 stmt = gimple_build_assign |
1634 (ptr, fold_build_pointer_plus_hwi_loc (input_location, | |
1635 ptr, | |
1636 fixed_offset)); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1637 gsi_insert_after (bsi, stmt, GSI_NEW_STMT); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1638 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1639 |
131 | 1640 if (!vtable_entry_type && (virtual_offset || indirect_offset != 0)) |
1641 { | |
1642 tree vfunc_type = make_node (FUNCTION_TYPE); | |
1643 TREE_TYPE (vfunc_type) = integer_type_node; | |
1644 TYPE_ARG_TYPES (vfunc_type) = NULL_TREE; | |
1645 layout_type (vfunc_type); | |
1646 | |
1647 vtable_entry_type = build_pointer_type (vfunc_type); | |
1648 } | |
1649 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1650 /* If there's a virtual offset, look up that value in the vtable and |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1651 adjust the pointer again. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1652 if (virtual_offset) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1653 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1654 tree vtabletmp; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1655 tree vtabletmp2; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1656 tree vtabletmp3; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1657 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1658 vtabletmp = |
111 | 1659 create_tmp_reg (build_pointer_type |
1660 (build_pointer_type (vtable_entry_type)), "vptr"); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1661 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1662 /* The vptr is always at offset zero in the object. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1663 stmt = gimple_build_assign (vtabletmp, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1664 build1 (NOP_EXPR, TREE_TYPE (vtabletmp), |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1665 ptr)); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1666 gsi_insert_after (bsi, stmt, GSI_NEW_STMT); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1667 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1668 /* Form the vtable address. */ |
111 | 1669 vtabletmp2 = create_tmp_reg (TREE_TYPE (TREE_TYPE (vtabletmp)), |
1670 "vtableaddr"); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1671 stmt = gimple_build_assign (vtabletmp2, |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1672 build_simple_mem_ref (vtabletmp)); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1673 gsi_insert_after (bsi, stmt, GSI_NEW_STMT); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1674 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1675 /* Find the entry with the vcall offset. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1676 stmt = gimple_build_assign (vtabletmp2, |
111 | 1677 fold_build_pointer_plus_loc (input_location, |
1678 vtabletmp2, | |
1679 virtual_offset)); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1680 gsi_insert_after (bsi, stmt, GSI_NEW_STMT); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1681 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1682 /* Get the offset itself. */ |
111 | 1683 vtabletmp3 = create_tmp_reg (TREE_TYPE (TREE_TYPE (vtabletmp2)), |
1684 "vcalloffset"); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1685 stmt = gimple_build_assign (vtabletmp3, |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1686 build_simple_mem_ref (vtabletmp2)); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1687 gsi_insert_after (bsi, stmt, GSI_NEW_STMT); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1688 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1689 /* Adjust the `this' pointer. */ |
111 | 1690 ptr = fold_build_pointer_plus_loc (input_location, ptr, vtabletmp3); |
1691 ptr = force_gimple_operand_gsi (bsi, ptr, true, NULL_TREE, false, | |
1692 GSI_CONTINUE_LINKING); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1693 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1694 |
131 | 1695 /* Likewise for an offset that is stored in the object that contains the |
1696 vtable. */ | |
1697 if (indirect_offset != 0) | |
1698 { | |
1699 tree offset_ptr, offset_tree; | |
1700 | |
1701 /* Get the address of the offset. */ | |
1702 offset_ptr | |
1703 = create_tmp_reg (build_pointer_type | |
1704 (build_pointer_type (vtable_entry_type)), | |
1705 "offset_ptr"); | |
1706 stmt = gimple_build_assign (offset_ptr, | |
1707 build1 (NOP_EXPR, TREE_TYPE (offset_ptr), | |
1708 ptr)); | |
1709 gsi_insert_after (bsi, stmt, GSI_NEW_STMT); | |
1710 | |
1711 stmt = gimple_build_assign | |
1712 (offset_ptr, | |
1713 fold_build_pointer_plus_hwi_loc (input_location, offset_ptr, | |
1714 indirect_offset)); | |
1715 gsi_insert_after (bsi, stmt, GSI_NEW_STMT); | |
1716 | |
1717 /* Get the offset itself. */ | |
1718 offset_tree = create_tmp_reg (TREE_TYPE (TREE_TYPE (offset_ptr)), | |
1719 "offset"); | |
1720 stmt = gimple_build_assign (offset_tree, | |
1721 build_simple_mem_ref (offset_ptr)); | |
1722 gsi_insert_after (bsi, stmt, GSI_NEW_STMT); | |
1723 | |
1724 /* Adjust the `this' pointer. */ | |
1725 ptr = fold_build_pointer_plus_loc (input_location, ptr, offset_tree); | |
1726 ptr = force_gimple_operand_gsi (bsi, ptr, true, NULL_TREE, false, | |
1727 GSI_CONTINUE_LINKING); | |
1728 } | |
1729 | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1730 if (!this_adjusting |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1731 && fixed_offset != 0) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1732 /* Adjust the pointer by the constant. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1733 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1734 tree ptrtmp; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1735 |
111 | 1736 if (VAR_P (ptr)) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1737 ptrtmp = ptr; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1738 else |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1739 { |
111 | 1740 ptrtmp = create_tmp_reg (TREE_TYPE (ptr), "ptr"); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1741 stmt = gimple_build_assign (ptrtmp, ptr); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1742 gsi_insert_after (bsi, stmt, GSI_NEW_STMT); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1743 } |
111 | 1744 ptr = fold_build_pointer_plus_hwi_loc (input_location, |
1745 ptrtmp, fixed_offset); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1746 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1747 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1748 /* Emit the statement and gimplify the adjustment expression. */ |
111 | 1749 ret = create_tmp_reg (TREE_TYPE (ptr), "adjusted_this"); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1750 stmt = gimple_build_assign (ret, ptr); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1751 gsi_insert_after (bsi, stmt, GSI_NEW_STMT); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1752 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1753 return ret; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1754 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1755 |
111 | 1756 /* Expand thunk NODE to gimple if possible. |
1757 When FORCE_GIMPLE_THUNK is true, gimple thunk is created and | |
1758 no assembler is produced. | |
1759 When OUTPUT_ASM_THUNK is true, also produce assembler for | |
1760 thunks that are not lowered. */ | |
1761 | |
1762 bool | |
1763 cgraph_node::expand_thunk (bool output_asm_thunks, bool force_gimple_thunk) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1764 { |
111 | 1765 bool this_adjusting = thunk.this_adjusting; |
1766 HOST_WIDE_INT fixed_offset = thunk.fixed_offset; | |
1767 HOST_WIDE_INT virtual_value = thunk.virtual_value; | |
131 | 1768 HOST_WIDE_INT indirect_offset = thunk.indirect_offset; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1769 tree virtual_offset = NULL; |
111 | 1770 tree alias = callees->callee->decl; |
1771 tree thunk_fndecl = decl; | |
1772 tree a; | |
1773 | |
1774 /* Instrumentation thunk is the same function with | |
1775 a different signature. Never need to expand it. */ | |
1776 if (thunk.add_pointer_bounds_args) | |
1777 return false; | |
1778 | |
131 | 1779 if (!force_gimple_thunk |
1780 && this_adjusting | |
1781 && indirect_offset == 0 | |
1782 && !DECL_EXTERNAL (alias) | |
1783 && !DECL_STATIC_CHAIN (alias) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1784 && targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1785 virtual_value, alias)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1786 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1787 const char *fnname; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1788 tree fn_block; |
111 | 1789 tree restype = TREE_TYPE (TREE_TYPE (thunk_fndecl)); |
1790 | |
1791 if (!output_asm_thunks) | |
1792 { | |
1793 analyzed = true; | |
1794 return false; | |
1795 } | |
1796 | |
1797 if (in_lto_p) | |
1798 get_untransformed_body (); | |
1799 a = DECL_ARGUMENTS (thunk_fndecl); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1800 |
111 | 1801 current_function_decl = thunk_fndecl; |
1802 | |
1803 /* Ensure thunks are emitted in their correct sections. */ | |
1804 resolve_unique_section (thunk_fndecl, 0, | |
1805 flag_function_sections); | |
1806 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1807 DECL_RESULT (thunk_fndecl) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1808 = build_decl (DECL_SOURCE_LOCATION (thunk_fndecl), |
111 | 1809 RESULT_DECL, 0, restype); |
1810 DECL_CONTEXT (DECL_RESULT (thunk_fndecl)) = thunk_fndecl; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1811 fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl)); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1812 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1813 /* The back end expects DECL_INITIAL to contain a BLOCK, so we |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1814 create one. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1815 fn_block = make_node (BLOCK); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1816 BLOCK_VARS (fn_block) = a; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1817 DECL_INITIAL (thunk_fndecl) = fn_block; |
111 | 1818 BLOCK_SUPERCONTEXT (fn_block) = thunk_fndecl; |
1819 allocate_struct_function (thunk_fndecl, false); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1820 init_function_start (thunk_fndecl); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1821 cfun->is_thunk = 1; |
111 | 1822 insn_locations_init (); |
1823 set_curr_insn_location (DECL_SOURCE_LOCATION (thunk_fndecl)); | |
1824 prologue_location = curr_insn_location (); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1825 assemble_start_function (thunk_fndecl, fnname); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1826 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1827 targetm.asm_out.output_mi_thunk (asm_out_file, thunk_fndecl, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1828 fixed_offset, virtual_value, alias); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1829 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1830 assemble_end_function (thunk_fndecl, fnname); |
111 | 1831 insn_locations_finalize (); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1832 init_insn_lengths (); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1833 free_after_compilation (cfun); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1834 TREE_ASM_WRITTEN (thunk_fndecl) = 1; |
111 | 1835 thunk.thunk_p = false; |
1836 analyzed = false; | |
1837 } | |
1838 else if (stdarg_p (TREE_TYPE (thunk_fndecl))) | |
1839 { | |
1840 error ("generic thunk code fails for method %qD which uses %<...%>", | |
1841 thunk_fndecl); | |
1842 TREE_ASM_WRITTEN (thunk_fndecl) = 1; | |
1843 analyzed = true; | |
1844 return false; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1845 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1846 else |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1847 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1848 tree restype; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1849 basic_block bb, then_bb, else_bb, return_bb; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1850 gimple_stmt_iterator bsi; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1851 int nargs = 0; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1852 tree arg; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1853 int i; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1854 tree resdecl; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1855 tree restmp = NULL; |
111 | 1856 |
1857 gcall *call; | |
1858 greturn *ret; | |
1859 bool alias_is_noreturn = TREE_THIS_VOLATILE (alias); | |
1860 | |
1861 /* We may be called from expand_thunk that releses body except for | |
1862 DECL_ARGUMENTS. In this case force_gimple_thunk is true. */ | |
1863 if (in_lto_p && !force_gimple_thunk) | |
1864 get_untransformed_body (); | |
131 | 1865 |
1866 /* We need to force DECL_IGNORED_P when the thunk is created | |
1867 after early debug was run. */ | |
1868 if (force_gimple_thunk) | |
1869 DECL_IGNORED_P (thunk_fndecl) = 1; | |
1870 | |
111 | 1871 a = DECL_ARGUMENTS (thunk_fndecl); |
1872 | |
1873 current_function_decl = thunk_fndecl; | |
1874 | |
1875 /* Ensure thunks are emitted in their correct sections. */ | |
1876 resolve_unique_section (thunk_fndecl, 0, | |
1877 flag_function_sections); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1878 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1879 bitmap_obstack_initialize (NULL); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1880 |
111 | 1881 if (thunk.virtual_offset_p) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1882 virtual_offset = size_int (virtual_value); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1883 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1884 /* Build the return declaration for the function. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1885 restype = TREE_TYPE (TREE_TYPE (thunk_fndecl)); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1886 if (DECL_RESULT (thunk_fndecl) == NULL_TREE) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1887 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1888 resdecl = build_decl (input_location, RESULT_DECL, 0, restype); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1889 DECL_ARTIFICIAL (resdecl) = 1; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1890 DECL_IGNORED_P (resdecl) = 1; |
131 | 1891 DECL_CONTEXT (resdecl) = thunk_fndecl; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1892 DECL_RESULT (thunk_fndecl) = resdecl; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1893 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1894 else |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1895 resdecl = DECL_RESULT (thunk_fndecl); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1896 |
131 | 1897 profile_count cfg_count = count; |
1898 if (!cfg_count.initialized_p ()) | |
1899 cfg_count = profile_count::from_gcov_type (BB_FREQ_MAX).guessed_local (); | |
1900 | |
111 | 1901 bb = then_bb = else_bb = return_bb |
131 | 1902 = init_lowered_empty_function (thunk_fndecl, true, cfg_count); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1903 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1904 bsi = gsi_start_bb (bb); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1905 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1906 /* Build call to the function being thunked. */ |
111 | 1907 if (!VOID_TYPE_P (restype) |
1908 && (!alias_is_noreturn | |
1909 || TREE_ADDRESSABLE (restype) | |
1910 || TREE_CODE (TYPE_SIZE_UNIT (restype)) != INTEGER_CST)) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1911 { |
111 | 1912 if (DECL_BY_REFERENCE (resdecl)) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1913 { |
111 | 1914 restmp = gimple_fold_indirect_ref (resdecl); |
1915 if (!restmp) | |
1916 restmp = build2 (MEM_REF, | |
1917 TREE_TYPE (TREE_TYPE (DECL_RESULT (alias))), | |
1918 resdecl, | |
1919 build_int_cst (TREE_TYPE | |
1920 (DECL_RESULT (alias)), 0)); | |
1921 } | |
1922 else if (!is_gimple_reg_type (restype)) | |
1923 { | |
1924 if (aggregate_value_p (resdecl, TREE_TYPE (thunk_fndecl))) | |
1925 { | |
1926 restmp = resdecl; | |
1927 | |
1928 if (VAR_P (restmp)) | |
131 | 1929 { |
1930 add_local_decl (cfun, restmp); | |
1931 BLOCK_VARS (DECL_INITIAL (current_function_decl)) | |
1932 = restmp; | |
1933 } | |
111 | 1934 } |
1935 else | |
1936 restmp = create_tmp_var (restype, "retval"); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1937 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1938 else |
111 | 1939 restmp = create_tmp_reg (restype, "retval"); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1940 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1941 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1942 for (arg = a; arg; arg = DECL_CHAIN (arg)) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1943 nargs++; |
111 | 1944 auto_vec<tree> vargs (nargs); |
1945 i = 0; | |
1946 arg = a; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1947 if (this_adjusting) |
111 | 1948 { |
1949 vargs.quick_push (thunk_adjust (&bsi, a, 1, fixed_offset, | |
131 | 1950 virtual_offset, indirect_offset)); |
111 | 1951 arg = DECL_CHAIN (a); |
1952 i = 1; | |
1953 } | |
1954 | |
1955 if (nargs) | |
1956 for (; i < nargs; i++, arg = DECL_CHAIN (arg)) | |
1957 { | |
1958 tree tmp = arg; | |
1959 if (VECTOR_TYPE_P (TREE_TYPE (arg)) | |
1960 || TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE) | |
1961 DECL_GIMPLE_REG_P (arg) = 1; | |
1962 | |
1963 if (!is_gimple_val (arg)) | |
1964 { | |
1965 tmp = create_tmp_reg (TYPE_MAIN_VARIANT | |
1966 (TREE_TYPE (arg)), "arg"); | |
1967 gimple *stmt = gimple_build_assign (tmp, arg); | |
1968 gsi_insert_after (&bsi, stmt, GSI_NEW_STMT); | |
1969 } | |
1970 vargs.quick_push (tmp); | |
1971 } | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1972 call = gimple_build_call_vec (build_fold_addr_expr_loc (0, alias), vargs); |
111 | 1973 callees->call_stmt = call; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
1974 gimple_call_set_from_thunk (call, true); |
131 | 1975 if (DECL_STATIC_CHAIN (alias)) |
1976 { | |
1977 tree p = DECL_STRUCT_FUNCTION (alias)->static_chain_decl; | |
1978 tree type = TREE_TYPE (p); | |
1979 tree decl = build_decl (DECL_SOURCE_LOCATION (thunk_fndecl), | |
1980 PARM_DECL, create_tmp_var_name ("CHAIN"), | |
1981 type); | |
1982 DECL_ARTIFICIAL (decl) = 1; | |
1983 DECL_IGNORED_P (decl) = 1; | |
1984 TREE_USED (decl) = 1; | |
1985 DECL_CONTEXT (decl) = thunk_fndecl; | |
1986 DECL_ARG_TYPE (decl) = type; | |
1987 TREE_READONLY (decl) = 1; | |
1988 | |
1989 struct function *sf = DECL_STRUCT_FUNCTION (thunk_fndecl); | |
1990 sf->static_chain_decl = decl; | |
1991 | |
1992 gimple_call_set_chain (call, decl); | |
1993 } | |
111 | 1994 |
1995 /* Return slot optimization is always possible and in fact requred to | |
1996 return values with DECL_BY_REFERENCE. */ | |
1997 if (aggregate_value_p (resdecl, TREE_TYPE (thunk_fndecl)) | |
1998 && (!is_gimple_reg_type (TREE_TYPE (resdecl)) | |
1999 || DECL_BY_REFERENCE (resdecl))) | |
2000 gimple_call_set_return_slot_opt (call, true); | |
2001 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2002 if (restmp) |
111 | 2003 { |
2004 gimple_call_set_lhs (call, restmp); | |
2005 gcc_assert (useless_type_conversion_p (TREE_TYPE (restmp), | |
2006 TREE_TYPE (TREE_TYPE (alias)))); | |
2007 } | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2008 gsi_insert_after (&bsi, call, GSI_NEW_STMT); |
111 | 2009 if (!alias_is_noreturn) |
2010 { | |
2011 if (restmp && !this_adjusting | |
2012 && (fixed_offset || virtual_offset)) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2013 { |
111 | 2014 tree true_label = NULL_TREE; |
2015 | |
2016 if (TREE_CODE (TREE_TYPE (restmp)) == POINTER_TYPE) | |
2017 { | |
2018 gimple *stmt; | |
2019 edge e; | |
2020 /* If the return type is a pointer, we need to | |
2021 protect against NULL. We know there will be an | |
2022 adjustment, because that's why we're emitting a | |
2023 thunk. */ | |
2024 then_bb = create_basic_block (NULL, bb); | |
131 | 2025 then_bb->count = cfg_count - cfg_count.apply_scale (1, 16); |
111 | 2026 return_bb = create_basic_block (NULL, then_bb); |
131 | 2027 return_bb->count = cfg_count; |
111 | 2028 else_bb = create_basic_block (NULL, else_bb); |
131 | 2029 else_bb->count = cfg_count.apply_scale (1, 16); |
111 | 2030 add_bb_to_loop (then_bb, bb->loop_father); |
2031 add_bb_to_loop (return_bb, bb->loop_father); | |
2032 add_bb_to_loop (else_bb, bb->loop_father); | |
2033 remove_edge (single_succ_edge (bb)); | |
2034 true_label = gimple_block_label (then_bb); | |
2035 stmt = gimple_build_cond (NE_EXPR, restmp, | |
2036 build_zero_cst (TREE_TYPE (restmp)), | |
2037 NULL_TREE, NULL_TREE); | |
2038 gsi_insert_after (&bsi, stmt, GSI_NEW_STMT); | |
2039 e = make_edge (bb, then_bb, EDGE_TRUE_VALUE); | |
2040 e->probability = profile_probability::guessed_always () | |
2041 .apply_scale (1, 16); | |
2042 e = make_edge (bb, else_bb, EDGE_FALSE_VALUE); | |
2043 e->probability = profile_probability::guessed_always () | |
2044 .apply_scale (1, 16); | |
2045 make_single_succ_edge (return_bb, | |
2046 EXIT_BLOCK_PTR_FOR_FN (cfun), 0); | |
2047 make_single_succ_edge (then_bb, return_bb, EDGE_FALLTHRU); | |
2048 e = make_edge (else_bb, return_bb, EDGE_FALLTHRU); | |
2049 e->probability = profile_probability::always (); | |
2050 bsi = gsi_last_bb (then_bb); | |
2051 } | |
2052 | |
2053 restmp = thunk_adjust (&bsi, restmp, /*this_adjusting=*/0, | |
131 | 2054 fixed_offset, virtual_offset, |
2055 indirect_offset); | |
111 | 2056 if (true_label) |
2057 { | |
2058 gimple *stmt; | |
2059 bsi = gsi_last_bb (else_bb); | |
2060 stmt = gimple_build_assign (restmp, | |
2061 build_zero_cst (TREE_TYPE (restmp))); | |
2062 gsi_insert_after (&bsi, stmt, GSI_NEW_STMT); | |
2063 bsi = gsi_last_bb (return_bb); | |
2064 } | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2065 } |
111 | 2066 else |
2067 gimple_call_set_tail (call, true); | |
2068 | |
2069 /* Build return value. */ | |
2070 if (!DECL_BY_REFERENCE (resdecl)) | |
2071 ret = gimple_build_return (restmp); | |
2072 else | |
2073 ret = gimple_build_return (resdecl); | |
2074 | |
2075 gsi_insert_after (&bsi, ret, GSI_NEW_STMT); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2076 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2077 else |
111 | 2078 { |
2079 gimple_call_set_tail (call, true); | |
2080 remove_edge (single_succ_edge (bb)); | |
2081 } | |
2082 | |
2083 cfun->gimple_df->in_ssa_p = true; | |
131 | 2084 update_max_bb_count (); |
111 | 2085 profile_status_for_fn (cfun) |
131 | 2086 = cfg_count.initialized_p () && cfg_count.ipa_p () |
2087 ? PROFILE_READ : PROFILE_GUESSED; | |
111 | 2088 /* FIXME: C++ FE should stop setting TREE_ASM_WRITTEN on thunks. */ |
2089 TREE_ASM_WRITTEN (thunk_fndecl) = false; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2090 delete_unreachable_blocks (); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2091 update_ssa (TODO_update_ssa); |
111 | 2092 checking_verify_flow_info (); |
2093 free_dominance_info (CDI_DOMINATORS); | |
2094 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2095 /* Since we want to emit the thunk, we explicitly mark its name as |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2096 referenced. */ |
111 | 2097 thunk.thunk_p = false; |
2098 lowered = true; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2099 bitmap_obstack_release (NULL); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2100 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2101 current_function_decl = NULL; |
111 | 2102 set_cfun (NULL); |
2103 return true; | |
0 | 2104 } |
2105 | |
111 | 2106 /* Assemble thunks and aliases associated to node. */ |
2107 | |
2108 void | |
2109 cgraph_node::assemble_thunks_and_aliases (void) | |
0 | 2110 { |
111 | 2111 cgraph_edge *e; |
2112 ipa_ref *ref; | |
2113 | |
2114 for (e = callers; e;) | |
2115 if (e->caller->thunk.thunk_p | |
2116 && !e->caller->global.inlined_to | |
2117 && !e->caller->thunk.add_pointer_bounds_args) | |
2118 { | |
2119 cgraph_node *thunk = e->caller; | |
2120 | |
2121 e = e->next_caller; | |
2122 thunk->expand_thunk (true, false); | |
2123 thunk->assemble_thunks_and_aliases (); | |
2124 } | |
2125 else | |
2126 e = e->next_caller; | |
2127 | |
2128 FOR_EACH_ALIAS (this, ref) | |
2129 { | |
2130 cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring); | |
2131 if (!alias->transparent_alias) | |
2132 { | |
2133 bool saved_written = TREE_ASM_WRITTEN (decl); | |
2134 | |
2135 /* Force assemble_alias to really output the alias this time instead | |
2136 of buffering it in same alias pairs. */ | |
2137 TREE_ASM_WRITTEN (decl) = 1; | |
2138 do_assemble_alias (alias->decl, | |
2139 DECL_ASSEMBLER_NAME (decl)); | |
2140 alias->assemble_thunks_and_aliases (); | |
2141 TREE_ASM_WRITTEN (decl) = saved_written; | |
2142 } | |
2143 } | |
2144 } | |
2145 | |
2146 /* Expand function specified by node. */ | |
2147 | |
2148 void | |
2149 cgraph_node::expand (void) | |
2150 { | |
2151 location_t saved_loc; | |
0 | 2152 |
2153 /* We ought to not compile any inline clones. */ | |
111 | 2154 gcc_assert (!global.inlined_to); |
2155 | |
2156 /* __RTL functions are compiled as soon as they are parsed, so don't | |
2157 do it again. */ | |
2158 if (native_rtl_p ()) | |
2159 return; | |
0 | 2160 |
2161 announce_function (decl); | |
111 | 2162 process = 0; |
2163 gcc_assert (lowered); | |
2164 get_untransformed_body (); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2165 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2166 /* Generate RTL for the body of DECL. */ |
111 | 2167 |
2168 timevar_push (TV_REST_OF_COMPILATION); | |
2169 | |
2170 gcc_assert (symtab->global_info_ready); | |
2171 | |
2172 /* Initialize the default bitmap obstack. */ | |
2173 bitmap_obstack_initialize (NULL); | |
2174 | |
2175 /* Initialize the RTL code for the function. */ | |
2176 saved_loc = input_location; | |
2177 input_location = DECL_SOURCE_LOCATION (decl); | |
2178 | |
2179 gcc_assert (DECL_STRUCT_FUNCTION (decl)); | |
2180 push_cfun (DECL_STRUCT_FUNCTION (decl)); | |
2181 init_function_start (decl); | |
2182 | |
2183 gimple_register_cfg_hooks (); | |
2184 | |
2185 bitmap_obstack_initialize (®_obstack); /* FIXME, only at RTL generation*/ | |
2186 | |
2187 execute_all_ipa_transforms (); | |
2188 | |
2189 /* Perform all tree transforms and optimizations. */ | |
2190 | |
2191 /* Signal the start of passes. */ | |
2192 invoke_plugin_callbacks (PLUGIN_ALL_PASSES_START, NULL); | |
2193 | |
2194 execute_pass_list (cfun, g->get_passes ()->all_passes); | |
2195 | |
2196 /* Signal the end of passes. */ | |
2197 invoke_plugin_callbacks (PLUGIN_ALL_PASSES_END, NULL); | |
2198 | |
2199 bitmap_obstack_release (®_obstack); | |
2200 | |
2201 /* Release the default bitmap obstack. */ | |
2202 bitmap_obstack_release (NULL); | |
2203 | |
2204 /* If requested, warn about function definitions where the function will | |
2205 return a value (usually of some struct or union type) which itself will | |
2206 take up a lot of stack space. */ | |
131 | 2207 if (!DECL_EXTERNAL (decl) && TREE_TYPE (decl)) |
111 | 2208 { |
2209 tree ret_type = TREE_TYPE (TREE_TYPE (decl)); | |
2210 | |
2211 if (ret_type && TYPE_SIZE_UNIT (ret_type) | |
2212 && TREE_CODE (TYPE_SIZE_UNIT (ret_type)) == INTEGER_CST | |
131 | 2213 && compare_tree_int (TYPE_SIZE_UNIT (ret_type), |
2214 warn_larger_than_size) > 0) | |
111 | 2215 { |
2216 unsigned int size_as_int | |
2217 = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ret_type)); | |
2218 | |
2219 if (compare_tree_int (TYPE_SIZE_UNIT (ret_type), size_as_int) == 0) | |
131 | 2220 warning (OPT_Wlarger_than_, |
2221 "size of return value of %q+D is %u bytes", | |
111 | 2222 decl, size_as_int); |
2223 else | |
131 | 2224 warning (OPT_Wlarger_than_, |
2225 "size of return value of %q+D is larger than %wu bytes", | |
2226 decl, warn_larger_than_size); | |
111 | 2227 } |
2228 } | |
2229 | |
2230 gimple_set_body (decl, NULL); | |
2231 if (DECL_STRUCT_FUNCTION (decl) == 0 | |
2232 && !cgraph_node::get (decl)->origin) | |
2233 { | |
2234 /* Stop pointing to the local nodes about to be freed. | |
2235 But DECL_INITIAL must remain nonzero so we know this | |
2236 was an actual function definition. | |
2237 For a nested function, this is done in c_pop_function_context. | |
2238 If rest_of_compilation set this to 0, leave it 0. */ | |
2239 if (DECL_INITIAL (decl) != 0) | |
2240 DECL_INITIAL (decl) = error_mark_node; | |
2241 } | |
2242 | |
2243 input_location = saved_loc; | |
2244 | |
2245 ggc_collect (); | |
2246 timevar_pop (TV_REST_OF_COMPILATION); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2247 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2248 /* Make sure that BE didn't give up on compiling. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2249 gcc_assert (TREE_ASM_WRITTEN (decl)); |
111 | 2250 if (cfun) |
2251 pop_cfun (); | |
2252 | |
2253 /* It would make a lot more sense to output thunks before function body to get more | |
2254 forward and lest backwarding jumps. This however would need solving problem | |
2255 with comdats. See PR48668. Also aliases must come after function itself to | |
2256 make one pass assemblers, like one on AIX, happy. See PR 50689. | |
2257 FIXME: Perhaps thunks should be move before function IFF they are not in comdat | |
2258 groups. */ | |
2259 assemble_thunks_and_aliases (); | |
2260 release_body (); | |
0 | 2261 /* Eliminate all call edges. This is important so the GIMPLE_CALL no longer |
2262 points to the dead function body. */ | |
111 | 2263 remove_callees (); |
2264 remove_all_references (); | |
0 | 2265 } |
2266 | |
111 | 2267 /* Node comparer that is responsible for the order that corresponds |
2268 to time when a function was launched for the first time. */ | |
2269 | |
2270 static int | |
2271 node_cmp (const void *pa, const void *pb) | |
0 | 2272 { |
111 | 2273 const cgraph_node *a = *(const cgraph_node * const *) pa; |
2274 const cgraph_node *b = *(const cgraph_node * const *) pb; | |
2275 | |
2276 /* Functions with time profile must be before these without profile. */ | |
2277 if (!a->tp_first_run || !b->tp_first_run) | |
2278 return a->tp_first_run - b->tp_first_run; | |
2279 | |
2280 return a->tp_first_run != b->tp_first_run | |
2281 ? b->tp_first_run - a->tp_first_run | |
2282 : b->order - a->order; | |
0 | 2283 } |
2284 | |
2285 /* Expand all functions that must be output. | |
2286 | |
2287 Attempt to topologically sort the nodes so function is output when | |
2288 all called functions are already assembled to allow data to be | |
2289 propagated across the callgraph. Use a stack to get smaller distance | |
2290 between a function and its callees (later we may choose to use a more | |
2291 sophisticated algorithm for function reordering; we will likely want | |
2292 to use subsections to make the output functions appear in top-down | |
2293 order). */ | |
2294 | |
2295 static void | |
111 | 2296 expand_all_functions (void) |
0 | 2297 { |
111 | 2298 cgraph_node *node; |
2299 cgraph_node **order = XCNEWVEC (cgraph_node *, | |
2300 symtab->cgraph_count); | |
2301 unsigned int expanded_func_count = 0, profiled_func_count = 0; | |
0 | 2302 int order_pos, new_order_pos = 0; |
2303 int i; | |
2304 | |
111 | 2305 order_pos = ipa_reverse_postorder (order); |
2306 gcc_assert (order_pos == symtab->cgraph_count); | |
0 | 2307 |
2308 /* Garbage collector may remove inline clones we eliminate during | |
2309 optimization. So we must be sure to not reference them. */ | |
2310 for (i = 0; i < order_pos; i++) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2311 if (order[i]->process) |
0 | 2312 order[new_order_pos++] = order[i]; |
2313 | |
111 | 2314 if (flag_profile_reorder_functions) |
2315 qsort (order, new_order_pos, sizeof (cgraph_node *), node_cmp); | |
2316 | |
0 | 2317 for (i = new_order_pos - 1; i >= 0; i--) |
2318 { | |
2319 node = order[i]; | |
111 | 2320 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2321 if (node->process) |
0 | 2322 { |
111 | 2323 expanded_func_count++; |
2324 if(node->tp_first_run) | |
2325 profiled_func_count++; | |
2326 | |
2327 if (symtab->dump_file) | |
2328 fprintf (symtab->dump_file, | |
2329 "Time profile order in expand_all_functions:%s:%d\n", | |
2330 node->asm_name (), node->tp_first_run); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2331 node->process = 0; |
111 | 2332 node->expand (); |
0 | 2333 } |
2334 } | |
111 | 2335 |
2336 if (dump_file) | |
2337 fprintf (dump_file, "Expanded functions with time profile (%s):%u/%u\n", | |
2338 main_input_filename, profiled_func_count, expanded_func_count); | |
2339 | |
2340 if (symtab->dump_file && flag_profile_reorder_functions) | |
2341 fprintf (symtab->dump_file, "Expanded functions with time profile:%u/%u\n", | |
2342 profiled_func_count, expanded_func_count); | |
2343 | |
2344 symtab->process_new_functions (); | |
2345 free_gimplify_stack (); | |
0 | 2346 |
2347 free (order); | |
2348 } | |
2349 | |
2350 /* This is used to sort the node types by the cgraph order number. */ | |
2351 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2352 enum cgraph_order_sort_kind |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2353 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2354 ORDER_UNDEFINED = 0, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2355 ORDER_FUNCTION, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2356 ORDER_VAR, |
111 | 2357 ORDER_VAR_UNDEF, |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2358 ORDER_ASM |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2359 }; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2360 |
0 | 2361 struct cgraph_order_sort |
2362 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2363 enum cgraph_order_sort_kind kind; |
0 | 2364 union |
2365 { | |
111 | 2366 cgraph_node *f; |
2367 varpool_node *v; | |
2368 asm_node *a; | |
0 | 2369 } u; |
2370 }; | |
2371 | |
2372 /* Output all functions, variables, and asm statements in the order | |
2373 according to their order fields, which is the order in which they | |
2374 appeared in the file. This implements -fno-toplevel-reorder. In | |
2375 this mode we may output functions and variables which don't really | |
2376 need to be output. */ | |
2377 | |
2378 static void | |
111 | 2379 output_in_order (void) |
0 | 2380 { |
2381 int max; | |
111 | 2382 cgraph_order_sort *nodes; |
0 | 2383 int i; |
111 | 2384 cgraph_node *pf; |
2385 varpool_node *pv; | |
2386 asm_node *pa; | |
2387 max = symtab->order; | |
2388 nodes = XCNEWVEC (cgraph_order_sort, max); | |
2389 | |
2390 FOR_EACH_DEFINED_FUNCTION (pf) | |
0 | 2391 { |
111 | 2392 if (pf->process && !pf->thunk.thunk_p && !pf->alias) |
0 | 2393 { |
111 | 2394 if (!pf->no_reorder) |
2395 continue; | |
0 | 2396 i = pf->order; |
2397 gcc_assert (nodes[i].kind == ORDER_UNDEFINED); | |
2398 nodes[i].kind = ORDER_FUNCTION; | |
2399 nodes[i].u.f = pf; | |
2400 } | |
2401 } | |
2402 | |
111 | 2403 /* There is a similar loop in symbol_table::output_variables. |
2404 Please keep them in sync. */ | |
2405 FOR_EACH_VARIABLE (pv) | |
0 | 2406 { |
111 | 2407 if (!pv->no_reorder) |
2408 continue; | |
2409 if (DECL_HARD_REGISTER (pv->decl) | |
2410 || DECL_HAS_VALUE_EXPR_P (pv->decl)) | |
2411 continue; | |
0 | 2412 i = pv->order; |
2413 gcc_assert (nodes[i].kind == ORDER_UNDEFINED); | |
111 | 2414 nodes[i].kind = pv->definition ? ORDER_VAR : ORDER_VAR_UNDEF; |
0 | 2415 nodes[i].u.v = pv; |
2416 } | |
2417 | |
111 | 2418 for (pa = symtab->first_asm_symbol (); pa; pa = pa->next) |
0 | 2419 { |
2420 i = pa->order; | |
2421 gcc_assert (nodes[i].kind == ORDER_UNDEFINED); | |
2422 nodes[i].kind = ORDER_ASM; | |
2423 nodes[i].u.a = pa; | |
2424 } | |
2425 | |
2426 /* In toplevel reorder mode we output all statics; mark them as needed. */ | |
2427 | |
2428 for (i = 0; i < max; ++i) | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2429 if (nodes[i].kind == ORDER_VAR) |
111 | 2430 nodes[i].u.v->finalize_named_section_flags (); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2431 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2432 for (i = 0; i < max; ++i) |
0 | 2433 { |
2434 switch (nodes[i].kind) | |
2435 { | |
2436 case ORDER_FUNCTION: | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2437 nodes[i].u.f->process = 0; |
111 | 2438 nodes[i].u.f->expand (); |
0 | 2439 break; |
2440 | |
2441 case ORDER_VAR: | |
111 | 2442 nodes[i].u.v->assemble_decl (); |
2443 break; | |
2444 | |
2445 case ORDER_VAR_UNDEF: | |
2446 assemble_undefined_decl (nodes[i].u.v->decl); | |
0 | 2447 break; |
2448 | |
2449 case ORDER_ASM: | |
2450 assemble_asm (nodes[i].u.a->asm_str); | |
2451 break; | |
2452 | |
2453 case ORDER_UNDEFINED: | |
2454 break; | |
2455 | |
2456 default: | |
2457 gcc_unreachable (); | |
2458 } | |
2459 } | |
2460 | |
111 | 2461 symtab->clear_asm_symbols (); |
2462 | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2463 free (nodes); |
0 | 2464 } |
2465 | |
2466 static void | |
2467 ipa_passes (void) | |
2468 { | |
111 | 2469 gcc::pass_manager *passes = g->get_passes (); |
2470 | |
0 | 2471 set_cfun (NULL); |
2472 current_function_decl = NULL; | |
2473 gimple_register_cfg_hooks (); | |
2474 bitmap_obstack_initialize (NULL); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2475 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2476 invoke_plugin_callbacks (PLUGIN_ALL_IPA_PASSES_START, NULL); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2477 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2478 if (!in_lto_p) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2479 { |
111 | 2480 execute_ipa_pass_list (passes->all_small_ipa_passes); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2481 if (seen_error ()) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2482 return; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2483 } |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2484 |
111 | 2485 /* This extra symtab_remove_unreachable_nodes pass tends to catch some |
2486 devirtualization and other changes where removal iterate. */ | |
2487 symtab->remove_unreachable_nodes (symtab->dump_file); | |
2488 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2489 /* If pass_all_early_optimizations was not scheduled, the state of |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2490 the cgraph will not be properly updated. Update it now. */ |
111 | 2491 if (symtab->state < IPA_SSA) |
2492 symtab->state = IPA_SSA; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2493 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2494 if (!in_lto_p) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2495 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2496 /* Generate coverage variables and constructors. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2497 coverage_finish (); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2498 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2499 /* Process new functions added. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2500 set_cfun (NULL); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2501 current_function_decl = NULL; |
111 | 2502 symtab->process_new_functions (); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2503 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2504 execute_ipa_summary_passes |
111 | 2505 ((ipa_opt_pass_d *) passes->all_regular_ipa_passes); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2506 } |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2507 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2508 /* Some targets need to handle LTO assembler output specially. */ |
111 | 2509 if (flag_generate_lto || flag_generate_offload) |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2510 targetm.asm_out.lto_start (); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2511 |
131 | 2512 if (!in_lto_p |
2513 || flag_incremental_link == INCREMENTAL_LINK_LTO) | |
111 | 2514 { |
131 | 2515 if (!quiet_flag) |
2516 fprintf (stderr, "Streaming LTO\n"); | |
111 | 2517 if (g->have_offload) |
2518 { | |
2519 section_name_prefix = OFFLOAD_SECTION_NAME_PREFIX; | |
2520 lto_stream_offload_p = true; | |
2521 ipa_write_summaries (); | |
2522 lto_stream_offload_p = false; | |
2523 } | |
2524 if (flag_lto) | |
2525 { | |
2526 section_name_prefix = LTO_SECTION_NAME_PREFIX; | |
2527 lto_stream_offload_p = false; | |
2528 ipa_write_summaries (); | |
2529 } | |
2530 } | |
2531 | |
2532 if (flag_generate_lto || flag_generate_offload) | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2533 targetm.asm_out.lto_end (); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2534 |
131 | 2535 if (!flag_ltrans |
2536 && ((in_lto_p && flag_incremental_link != INCREMENTAL_LINK_LTO) | |
2537 || !flag_lto || flag_fat_lto_objects)) | |
111 | 2538 execute_ipa_pass_list (passes->all_regular_ipa_passes); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2539 invoke_plugin_callbacks (PLUGIN_ALL_IPA_PASSES_END, NULL); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2540 |
0 | 2541 bitmap_obstack_release (NULL); |
2542 } | |
2543 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2544 |
111 | 2545 /* Return string alias is alias of. */ |
2546 | |
2547 static tree | |
2548 get_alias_symbol (tree decl) | |
2549 { | |
2550 tree alias = lookup_attribute ("alias", DECL_ATTRIBUTES (decl)); | |
2551 return get_identifier (TREE_STRING_POINTER | |
2552 (TREE_VALUE (TREE_VALUE (alias)))); | |
2553 } | |
2554 | |
2555 | |
2556 /* Weakrefs may be associated to external decls and thus not output | |
2557 at expansion time. Emit all necessary aliases. */ | |
2558 | |
2559 void | |
2560 symbol_table::output_weakrefs (void) | |
2561 { | |
2562 symtab_node *node; | |
2563 FOR_EACH_SYMBOL (node) | |
2564 if (node->alias | |
2565 && !TREE_ASM_WRITTEN (node->decl) | |
2566 && node->weakref) | |
2567 { | |
2568 tree target; | |
2569 | |
2570 /* Weakrefs are special by not requiring target definition in current | |
2571 compilation unit. It is thus bit hard to work out what we want to | |
2572 alias. | |
2573 When alias target is defined, we need to fetch it from symtab reference, | |
2574 otherwise it is pointed to by alias_target. */ | |
2575 if (node->alias_target) | |
2576 target = (DECL_P (node->alias_target) | |
2577 ? DECL_ASSEMBLER_NAME (node->alias_target) | |
2578 : node->alias_target); | |
2579 else if (node->analyzed) | |
2580 target = DECL_ASSEMBLER_NAME (node->get_alias_target ()->decl); | |
2581 else | |
2582 { | |
2583 gcc_unreachable (); | |
2584 target = get_alias_symbol (node->decl); | |
2585 } | |
2586 do_assemble_alias (node->decl, target); | |
2587 } | |
2588 } | |
2589 | |
0 | 2590 /* Perform simple optimizations based on callgraph. */ |
2591 | |
2592 void | |
111 | 2593 symbol_table::compile (void) |
0 | 2594 { |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2595 if (seen_error ()) |
0 | 2596 return; |
2597 | |
111 | 2598 symtab_node::checking_verify_symtab_nodes (); |
0 | 2599 |
2600 timevar_push (TV_CGRAPHOPT); | |
2601 if (pre_ipa_mem_report) | |
2602 { | |
2603 fprintf (stderr, "Memory consumption before IPA\n"); | |
2604 dump_memory_report (false); | |
2605 } | |
2606 if (!quiet_flag) | |
2607 fprintf (stderr, "Performing interprocedural optimizations\n"); | |
111 | 2608 state = IPA; |
2609 | |
2610 /* If LTO is enabled, initialize the streamer hooks needed by GIMPLE. */ | |
2611 if (flag_generate_lto || flag_generate_offload) | |
2612 lto_streamer_hooks_init (); | |
0 | 2613 |
2614 /* Don't run the IPA passes if there was any error or sorry messages. */ | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2615 if (!seen_error ()) |
0 | 2616 ipa_passes (); |
2617 | |
111 | 2618 /* Do nothing else if any IPA pass found errors or if we are just streaming LTO. */ |
2619 if (seen_error () | |
131 | 2620 || ((!in_lto_p || flag_incremental_link == INCREMENTAL_LINK_LTO) |
2621 && flag_lto && !flag_fat_lto_objects)) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2622 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2623 timevar_pop (TV_CGRAPHOPT); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2624 return; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2625 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2626 |
111 | 2627 global_info_ready = true; |
2628 if (dump_file) | |
0 | 2629 { |
111 | 2630 fprintf (dump_file, "Optimized "); |
2631 symtab->dump (dump_file); | |
0 | 2632 } |
2633 if (post_ipa_mem_report) | |
2634 { | |
2635 fprintf (stderr, "Memory consumption after IPA\n"); | |
2636 dump_memory_report (false); | |
2637 } | |
2638 timevar_pop (TV_CGRAPHOPT); | |
2639 | |
2640 /* Output everything. */ | |
131 | 2641 switch_to_section (text_section); |
36 | 2642 (*debug_hooks->assembly_start) (); |
0 | 2643 if (!quiet_flag) |
2644 fprintf (stderr, "Assembling functions:\n"); | |
111 | 2645 symtab_node::checking_verify_symtab_nodes (); |
2646 | |
2647 bitmap_obstack_initialize (NULL); | |
2648 execute_ipa_pass_list (g->get_passes ()->all_late_ipa_passes); | |
2649 bitmap_obstack_release (NULL); | |
2650 mark_functions_to_output (); | |
2651 | |
2652 /* When weakref support is missing, we automatically translate all | |
2653 references to NODE to references to its ultimate alias target. | |
2654 The renaming mechanizm uses flag IDENTIFIER_TRANSPARENT_ALIAS and | |
2655 TREE_CHAIN. | |
2656 | |
2657 Set up this mapping before we output any assembler but once we are sure | |
2658 that all symbol renaming is done. | |
2659 | |
2660 FIXME: All this uglyness can go away if we just do renaming at gimple | |
2661 level by physically rewritting the IL. At the moment we can only redirect | |
2662 calls, so we need infrastructure for renaming references as well. */ | |
2663 #ifndef ASM_OUTPUT_WEAKREF | |
2664 symtab_node *node; | |
2665 | |
2666 FOR_EACH_SYMBOL (node) | |
2667 if (node->alias | |
2668 && lookup_attribute ("weakref", DECL_ATTRIBUTES (node->decl))) | |
2669 { | |
2670 IDENTIFIER_TRANSPARENT_ALIAS | |
2671 (DECL_ASSEMBLER_NAME (node->decl)) = 1; | |
2672 TREE_CHAIN (DECL_ASSEMBLER_NAME (node->decl)) | |
2673 = (node->alias_target ? node->alias_target | |
2674 : DECL_ASSEMBLER_NAME (node->get_alias_target ()->decl)); | |
2675 } | |
0 | 2676 #endif |
2677 | |
111 | 2678 state = EXPANSION; |
2679 | |
2680 /* Output first asm statements and anything ordered. The process | |
2681 flag is cleared for these nodes, so we skip them later. */ | |
2682 output_in_order (); | |
2683 expand_all_functions (); | |
2684 output_variables (); | |
2685 | |
2686 process_new_functions (); | |
2687 state = FINISHED; | |
2688 output_weakrefs (); | |
2689 | |
2690 if (dump_file) | |
0 | 2691 { |
111 | 2692 fprintf (dump_file, "\nFinal "); |
2693 symtab->dump (dump_file); | |
0 | 2694 } |
111 | 2695 if (!flag_checking) |
2696 return; | |
2697 symtab_node::verify_symtab_nodes (); | |
0 | 2698 /* Double check that all inline clones are gone and that all |
2699 function bodies have been released from memory. */ | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2700 if (!seen_error ()) |
0 | 2701 { |
111 | 2702 cgraph_node *node; |
0 | 2703 bool error_found = false; |
2704 | |
111 | 2705 FOR_EACH_DEFINED_FUNCTION (node) |
2706 if (node->global.inlined_to | |
2707 || gimple_has_body_p (node->decl)) | |
0 | 2708 { |
2709 error_found = true; | |
111 | 2710 node->debug (); |
0 | 2711 } |
2712 if (error_found) | |
2713 internal_error ("nodes with unreleased memory found"); | |
2714 } | |
2715 } | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2716 |
131 | 2717 /* Earlydebug dump file, flags, and number. */ |
2718 | |
2719 static int debuginfo_early_dump_nr; | |
2720 static FILE *debuginfo_early_dump_file; | |
2721 static dump_flags_t debuginfo_early_dump_flags; | |
2722 | |
2723 /* Debug dump file, flags, and number. */ | |
2724 | |
2725 static int debuginfo_dump_nr; | |
2726 static FILE *debuginfo_dump_file; | |
2727 static dump_flags_t debuginfo_dump_flags; | |
2728 | |
2729 /* Register the debug and earlydebug dump files. */ | |
2730 | |
2731 void | |
2732 debuginfo_early_init (void) | |
2733 { | |
2734 gcc::dump_manager *dumps = g->get_dumps (); | |
2735 debuginfo_early_dump_nr = dumps->dump_register (".earlydebug", "earlydebug", | |
2736 "earlydebug", DK_tree, | |
2737 OPTGROUP_NONE, | |
2738 false); | |
2739 debuginfo_dump_nr = dumps->dump_register (".debug", "debug", | |
2740 "debug", DK_tree, | |
2741 OPTGROUP_NONE, | |
2742 false); | |
2743 } | |
2744 | |
2745 /* Initialize the debug and earlydebug dump files. */ | |
2746 | |
2747 void | |
2748 debuginfo_init (void) | |
2749 { | |
2750 gcc::dump_manager *dumps = g->get_dumps (); | |
2751 debuginfo_dump_file = dump_begin (debuginfo_dump_nr, NULL); | |
2752 debuginfo_dump_flags = dumps->get_dump_file_info (debuginfo_dump_nr)->pflags; | |
2753 debuginfo_early_dump_file = dump_begin (debuginfo_early_dump_nr, NULL); | |
2754 debuginfo_early_dump_flags | |
2755 = dumps->get_dump_file_info (debuginfo_early_dump_nr)->pflags; | |
2756 } | |
2757 | |
2758 /* Finalize the debug and earlydebug dump files. */ | |
2759 | |
2760 void | |
2761 debuginfo_fini (void) | |
2762 { | |
2763 if (debuginfo_dump_file) | |
2764 dump_end (debuginfo_dump_nr, debuginfo_dump_file); | |
2765 if (debuginfo_early_dump_file) | |
2766 dump_end (debuginfo_early_dump_nr, debuginfo_early_dump_file); | |
2767 } | |
2768 | |
2769 /* Set dump_file to the debug dump file. */ | |
2770 | |
2771 void | |
2772 debuginfo_start (void) | |
2773 { | |
2774 set_dump_file (debuginfo_dump_file); | |
2775 } | |
2776 | |
2777 /* Undo setting dump_file to the debug dump file. */ | |
2778 | |
2779 void | |
2780 debuginfo_stop (void) | |
2781 { | |
2782 set_dump_file (NULL); | |
2783 } | |
2784 | |
2785 /* Set dump_file to the earlydebug dump file. */ | |
2786 | |
2787 void | |
2788 debuginfo_early_start (void) | |
2789 { | |
2790 set_dump_file (debuginfo_early_dump_file); | |
2791 } | |
2792 | |
2793 /* Undo setting dump_file to the earlydebug dump file. */ | |
2794 | |
2795 void | |
2796 debuginfo_early_stop (void) | |
2797 { | |
2798 set_dump_file (NULL); | |
2799 } | |
111 | 2800 |
2801 /* Analyze the whole compilation unit once it is parsed completely. */ | |
2802 | |
0 | 2803 void |
111 | 2804 symbol_table::finalize_compilation_unit (void) |
0 | 2805 { |
111 | 2806 timevar_push (TV_CGRAPH); |
2807 | |
2808 /* If we're here there's no current function anymore. Some frontends | |
2809 are lazy in clearing these. */ | |
2810 current_function_decl = NULL; | |
2811 set_cfun (NULL); | |
2812 | |
2813 /* Do not skip analyzing the functions if there were errors, we | |
2814 miss diagnostics for following functions otherwise. */ | |
2815 | |
2816 /* Emit size functions we didn't inline. */ | |
2817 finalize_size_functions (); | |
2818 | |
2819 /* Mark alias targets necessary and emit diagnostics. */ | |
2820 handle_alias_pairs (); | |
2821 | |
2822 if (!quiet_flag) | |
0 | 2823 { |
111 | 2824 fprintf (stderr, "\nAnalyzing compilation unit\n"); |
2825 fflush (stderr); | |
0 | 2826 } |
111 | 2827 |
2828 if (flag_dump_passes) | |
2829 dump_passes (); | |
2830 | |
2831 /* Gimplify and lower all functions, compute reachability and | |
2832 remove unreachable nodes. */ | |
2833 analyze_functions (/*first_time=*/true); | |
2834 | |
2835 /* Mark alias targets necessary and emit diagnostics. */ | |
2836 handle_alias_pairs (); | |
2837 | |
2838 /* Gimplify and lower thunks. */ | |
2839 analyze_functions (/*first_time=*/false); | |
2840 | |
2841 /* Offloading requires LTO infrastructure. */ | |
2842 if (!in_lto_p && g->have_offload) | |
2843 flag_generate_offload = 1; | |
2844 | |
2845 if (!seen_error ()) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2846 { |
111 | 2847 /* Emit early debug for reachable functions, and by consequence, |
2848 locally scoped symbols. */ | |
2849 struct cgraph_node *cnode; | |
2850 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (cnode) | |
2851 (*debug_hooks->early_global_decl) (cnode->decl); | |
2852 | |
2853 /* Clean up anything that needs cleaning up after initial debug | |
2854 generation. */ | |
131 | 2855 debuginfo_early_start (); |
111 | 2856 (*debug_hooks->early_finish) (main_input_filename); |
131 | 2857 debuginfo_early_stop (); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2858 } |
111 | 2859 |
2860 /* Finally drive the pass manager. */ | |
2861 compile (); | |
2862 | |
2863 timevar_pop (TV_CGRAPH); | |
0 | 2864 } |
2865 | |
111 | 2866 /* Reset all state within cgraphunit.c so that we can rerun the compiler |
2867 within the same process. For use by toplev::finalize. */ | |
2868 | |
2869 void | |
2870 cgraphunit_c_finalize (void) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2871 { |
111 | 2872 gcc_assert (cgraph_new_nodes.length () == 0); |
2873 cgraph_new_nodes.truncate (0); | |
2874 | |
2875 vtable_entry_type = NULL; | |
2876 queued_nodes = &symtab_terminator; | |
2877 | |
2878 first_analyzed = NULL; | |
2879 first_analyzed_var = NULL; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2880 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2881 |
111 | 2882 /* Creates a wrapper from cgraph_node to TARGET node. Thunk is used for this |
2883 kind of wrapper method. */ | |
2884 | |
2885 void | |
2886 cgraph_node::create_wrapper (cgraph_node *target) | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2887 { |
111 | 2888 /* Preserve DECL_RESULT so we get right by reference flag. */ |
2889 tree decl_result = DECL_RESULT (decl); | |
2890 | |
2891 /* Remove the function's body but keep arguments to be reused | |
2892 for thunk. */ | |
2893 release_body (true); | |
2894 reset (); | |
2895 | |
2896 DECL_UNINLINABLE (decl) = false; | |
2897 DECL_RESULT (decl) = decl_result; | |
2898 DECL_INITIAL (decl) = NULL; | |
2899 allocate_struct_function (decl, false); | |
2900 set_cfun (NULL); | |
2901 | |
2902 /* Turn alias into thunk and expand it into GIMPLE representation. */ | |
2903 definition = true; | |
2904 | |
2905 memset (&thunk, 0, sizeof (cgraph_thunk_info)); | |
2906 thunk.thunk_p = true; | |
131 | 2907 create_edge (target, NULL, count); |
111 | 2908 callees->can_throw_external = !TREE_NOTHROW (target->decl); |
2909 | |
2910 tree arguments = DECL_ARGUMENTS (decl); | |
2911 | |
2912 while (arguments) | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2913 { |
111 | 2914 TREE_ADDRESSABLE (arguments) = false; |
2915 arguments = TREE_CHAIN (arguments); | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2916 } |
111 | 2917 |
2918 expand_thunk (false, true); | |
2919 | |
2920 /* Inline summary set-up. */ | |
2921 analyze (); | |
2922 inline_analyze_function (this); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2923 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
36
diff
changeset
|
2924 |
0 | 2925 #include "gt-cgraphunit.h" |