5a67431cc1f2eff65c7199d5af81bad12be56317
[gcc.git] / gcc / cp / optimize.c
1 /* Perform optimizations on tree structure.
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2007, 2008, 2009
3 Free Software Foundation, Inc.
4 Written by Mark Michell (mark@codesourcery.com).
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
12
13 GCC is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
21
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "tree.h"
27 #include "cp-tree.h"
28 #include "rtl.h"
29 #include "insn-config.h"
30 #include "input.h"
31 #include "integrate.h"
32 #include "toplev.h"
33 #include "varray.h"
34 #include "params.h"
35 #include "hashtab.h"
36 #include "target.h"
37 #include "debug.h"
38 #include "tree-inline.h"
39 #include "flags.h"
40 #include "langhooks.h"
41 #include "diagnostic.h"
42 #include "tree-dump.h"
43 #include "gimple.h"
44 #include "tree-iterator.h"
45 #include "cgraph.h"
46
47 /* Prototypes. */
48
49 static void update_cloned_parm (tree, tree, bool);
50
51 /* CLONED_PARM is a copy of CLONE, generated for a cloned constructor
52 or destructor. Update it to ensure that the source-position for
53 the cloned parameter matches that for the original, and that the
54 debugging generation code will be able to find the original PARM. */
55
56 static void
57 update_cloned_parm (tree parm, tree cloned_parm, bool first)
58 {
59 DECL_ABSTRACT_ORIGIN (cloned_parm) = parm;
60
61 /* We may have taken its address. */
62 TREE_ADDRESSABLE (cloned_parm) = TREE_ADDRESSABLE (parm);
63
64 /* The definition might have different constness. */
65 TREE_READONLY (cloned_parm) = TREE_READONLY (parm);
66
67 TREE_USED (cloned_parm) = !first || TREE_USED (parm);
68
69 /* The name may have changed from the declaration. */
70 DECL_NAME (cloned_parm) = DECL_NAME (parm);
71 DECL_SOURCE_LOCATION (cloned_parm) = DECL_SOURCE_LOCATION (parm);
72 TREE_TYPE (cloned_parm) = TREE_TYPE (parm);
73
74 DECL_GIMPLE_REG_P (cloned_parm) = DECL_GIMPLE_REG_P (parm);
75 }
76
77
78 /* FN is a function in High GIMPLE form that has a complete body and no
79 CFG. CLONE is a function whose body is to be set to a copy of FN,
80 mapping argument declarations according to the ARG_MAP splay_tree. */
81
82 static void
83 clone_body (tree clone, tree fn, void *arg_map)
84 {
85 copy_body_data id;
86 tree stmts;
87
88 /* Clone the body, as if we were making an inline call. But, remap
89 the parameters in the callee to the parameters of caller. */
90 memset (&id, 0, sizeof (id));
91 id.src_fn = fn;
92 id.dst_fn = clone;
93 id.src_cfun = DECL_STRUCT_FUNCTION (fn);
94 id.decl_map = (struct pointer_map_t *) arg_map;
95
96 id.copy_decl = copy_decl_no_change;
97 id.transform_call_graph_edges = CB_CGE_DUPLICATE;
98 id.transform_new_cfg = true;
99 id.transform_return_to_modify = false;
100 id.transform_lang_insert_block = NULL;
101
102 /* We're not inside any EH region. */
103 id.eh_lp_nr = 0;
104
105 stmts = DECL_SAVED_TREE (fn);
106 walk_tree (&stmts, copy_tree_body_r, &id, NULL);
107 append_to_statement_list_force (stmts, &DECL_SAVED_TREE (clone));
108 }
109
110 /* DELETE_DTOR is a delete destructor whose body will be built.
111 COMPLETE_DTOR is the corresponding complete destructor. */
112
113 static void
114 build_delete_destructor_body (tree delete_dtor, tree complete_dtor)
115 {
116 tree call_dtor, call_delete;
117 tree parm = DECL_ARGUMENTS (delete_dtor);
118 tree virtual_size = cxx_sizeof (current_class_type);
119
120 /* Call the corresponding complete destructor. */
121 gcc_assert (complete_dtor);
122 call_dtor = build_cxx_call (complete_dtor, 1, &parm);
123 add_stmt (call_dtor);
124
125 add_stmt (build_stmt (0, LABEL_EXPR, cdtor_label));
126
127 /* Call the delete function. */
128 call_delete = build_op_delete_call (DELETE_EXPR, current_class_ptr,
129 virtual_size,
130 /*global_p=*/false,
131 /*placement=*/NULL_TREE,
132 /*alloc_fn=*/NULL_TREE);
133 add_stmt (call_delete);
134
135 /* Return the address of the object. */
136 if (targetm.cxx.cdtor_returns_this ())
137 {
138 tree val = DECL_ARGUMENTS (delete_dtor);
139 val = build2 (MODIFY_EXPR, TREE_TYPE (val),
140 DECL_RESULT (delete_dtor), val);
141 add_stmt (build_stmt (0, RETURN_EXPR, val));
142 }
143 }
144
145 /* Return name of comdat group for complete and base ctor (or dtor)
146 that have the same body. If dtor is virtual, deleting dtor goes
147 into this comdat group as well. */
148
149 static tree
150 cdtor_comdat_group (tree complete, tree base)
151 {
152 tree complete_name = DECL_COMDAT_GROUP (complete);
153 tree base_name = DECL_COMDAT_GROUP (base);
154 char *grp_name;
155 const char *p, *q;
156 bool diff_seen = false;
157 size_t idx;
158 if (complete_name == NULL)
159 complete_name = cxx_comdat_group (complete);
160 if (base_name == NULL)
161 base_name = cxx_comdat_group (base);
162 gcc_assert (IDENTIFIER_LENGTH (complete_name)
163 == IDENTIFIER_LENGTH (base_name));
164 grp_name = XALLOCAVEC (char, IDENTIFIER_LENGTH (complete_name) + 1);
165 p = IDENTIFIER_POINTER (complete_name);
166 q = IDENTIFIER_POINTER (base_name);
167 for (idx = 0; idx < IDENTIFIER_LENGTH (complete_name); idx++)
168 if (p[idx] == q[idx])
169 grp_name[idx] = p[idx];
170 else
171 {
172 gcc_assert (!diff_seen
173 && idx > 0
174 && (p[idx - 1] == 'C' || p[idx - 1] == 'D')
175 && p[idx] == '1'
176 && q[idx] == '2');
177 grp_name[idx] = '5';
178 diff_seen = true;
179 }
180 grp_name[idx] = '\0';
181 gcc_assert (diff_seen);
182 return get_identifier (grp_name);
183 }
184
185 /* FN is a function that has a complete body. Clone the body as
186 necessary. Returns nonzero if there's no longer any need to
187 process the main body. */
188
189 bool
190 maybe_clone_body (tree fn)
191 {
192 tree comdat_group = NULL_TREE;
193 tree clone;
194 tree fns[3];
195 bool first = true;
196 bool in_charge_parm_used;
197 int idx;
198
199 /* We only clone constructors and destructors. */
200 if (!DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn)
201 && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn))
202 return 0;
203
204 /* Emit the DWARF1 abstract instance. */
205 (*debug_hooks->deferred_inline_function) (fn);
206
207 in_charge_parm_used = CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fn)) != NULL;
208 fns[0] = NULL_TREE;
209 fns[1] = NULL_TREE;
210 fns[2] = NULL_TREE;
211
212 /* Look for the complete destructor which may be used to build the
213 delete destructor. */
214 FOR_EACH_CLONE (clone, fn)
215 if (DECL_NAME (clone) == complete_dtor_identifier
216 || DECL_NAME (clone) == complete_ctor_identifier)
217 fns[1] = clone;
218 else if (DECL_NAME (clone) == base_dtor_identifier
219 || DECL_NAME (clone) == base_ctor_identifier)
220 fns[0] = clone;
221 else if (DECL_NAME (clone) == deleting_dtor_identifier)
222 fns[2] = clone;
223 else
224 gcc_unreachable ();
225
226 /* We know that any clones immediately follow FN in the TYPE_METHODS
227 list. */
228 push_to_top_level ();
229 for (idx = 0; idx < 3; idx++)
230 {
231 tree parm;
232 tree clone_parm;
233 int parmno;
234 bool alias = false;
235 struct pointer_map_t *decl_map;
236
237 clone = fns[idx];
238 if (!clone)
239 continue;
240
241 /* Update CLONE's source position information to match FN's. */
242 DECL_SOURCE_LOCATION (clone) = DECL_SOURCE_LOCATION (fn);
243 DECL_DECLARED_INLINE_P (clone) = DECL_DECLARED_INLINE_P (fn);
244 DECL_COMDAT (clone) = DECL_COMDAT (fn);
245 DECL_WEAK (clone) = DECL_WEAK (fn);
246
247 /* We don't copy the comdat group from fn to clone because the assembler
248 name of fn was corrupted by write_mangled_name by adding *INTERNAL*
249 to it. By doing so, it also corrupted the comdat group. */
250 if (DECL_ONE_ONLY (fn))
251 DECL_COMDAT_GROUP (clone) = cxx_comdat_group (clone);
252 DECL_SECTION_NAME (clone) = DECL_SECTION_NAME (fn);
253 DECL_USE_TEMPLATE (clone) = DECL_USE_TEMPLATE (fn);
254 DECL_EXTERNAL (clone) = DECL_EXTERNAL (fn);
255 DECL_INTERFACE_KNOWN (clone) = DECL_INTERFACE_KNOWN (fn);
256 DECL_NOT_REALLY_EXTERN (clone) = DECL_NOT_REALLY_EXTERN (fn);
257 TREE_PUBLIC (clone) = TREE_PUBLIC (fn);
258 DECL_VISIBILITY (clone) = DECL_VISIBILITY (fn);
259 DECL_VISIBILITY_SPECIFIED (clone) = DECL_VISIBILITY_SPECIFIED (fn);
260 DECL_DLLIMPORT_P (clone) = DECL_DLLIMPORT_P (fn);
261 DECL_ATTRIBUTES (clone) = copy_list (DECL_ATTRIBUTES (fn));
262 DECL_DISREGARD_INLINE_LIMITS (clone) = DECL_DISREGARD_INLINE_LIMITS (fn);
263
264 /* Adjust the parameter names and locations. */
265 parm = DECL_ARGUMENTS (fn);
266 clone_parm = DECL_ARGUMENTS (clone);
267 /* Update the `this' parameter, which is always first. */
268 update_cloned_parm (parm, clone_parm, first);
269 parm = TREE_CHAIN (parm);
270 clone_parm = TREE_CHAIN (clone_parm);
271 if (DECL_HAS_IN_CHARGE_PARM_P (fn))
272 parm = TREE_CHAIN (parm);
273 if (DECL_HAS_VTT_PARM_P (fn))
274 parm = TREE_CHAIN (parm);
275 if (DECL_HAS_VTT_PARM_P (clone))
276 clone_parm = TREE_CHAIN (clone_parm);
277 for (; parm;
278 parm = TREE_CHAIN (parm), clone_parm = TREE_CHAIN (clone_parm))
279 /* Update this parameter. */
280 update_cloned_parm (parm, clone_parm, first);
281
282 /* Start processing the function. */
283 start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED);
284
285 /* Tell cgraph if both ctors or both dtors are known to have
286 the same body. */
287 if (!in_charge_parm_used
288 && fns[0]
289 && idx == 1
290 && !flag_use_repository
291 && DECL_INTERFACE_KNOWN (fns[0])
292 && (SUPPORTS_ONE_ONLY || !DECL_WEAK (fns[0]))
293 && (!DECL_ONE_ONLY (fns[0])
294 || (HAVE_COMDAT_GROUP
295 && DECL_WEAK (fns[0])
296 /* Don't optimize synthetized virtual dtors, because then
297 the deleting and other dtors are emitted when needed
298 and so it is not certain we would emit both
299 deleting and complete/base dtors in the comdat group. */
300 && (fns[2] == NULL || !DECL_ARTIFICIAL (fn))))
301 && cgraph_same_body_alias (clone, fns[0]))
302 {
303 alias = true;
304 if (DECL_ONE_ONLY (fns[0]))
305 {
306 /* For comdat base and complete cdtors put them
307 into the same, *[CD]5* comdat group instead of
308 *[CD][12]*. */
309 comdat_group = cdtor_comdat_group (fns[1], fns[0]);
310 DECL_COMDAT_GROUP (fns[0]) = comdat_group;
311 }
312 emit_associated_thunks (clone);
313 }
314
315 /* Build the delete destructor by calling complete destructor
316 and delete function. */
317 if (idx == 2)
318 build_delete_destructor_body (clone, fns[1]);
319 else if (alias)
320 /* No need to populate body. */ ;
321 else
322 {
323 /* Remap the parameters. */
324 decl_map = pointer_map_create ();
325 for (parmno = 0,
326 parm = DECL_ARGUMENTS (fn),
327 clone_parm = DECL_ARGUMENTS (clone);
328 parm;
329 ++parmno,
330 parm = TREE_CHAIN (parm))
331 {
332 /* Map the in-charge parameter to an appropriate constant. */
333 if (DECL_HAS_IN_CHARGE_PARM_P (fn) && parmno == 1)
334 {
335 tree in_charge;
336 in_charge = in_charge_arg_for_name (DECL_NAME (clone));
337 *pointer_map_insert (decl_map, parm) = in_charge;
338 }
339 else if (DECL_ARTIFICIAL (parm)
340 && DECL_NAME (parm) == vtt_parm_identifier)
341 {
342 /* For a subobject constructor or destructor, the next
343 argument is the VTT parameter. Remap the VTT_PARM
344 from the CLONE to this parameter. */
345 if (DECL_HAS_VTT_PARM_P (clone))
346 {
347 DECL_ABSTRACT_ORIGIN (clone_parm) = parm;
348 *pointer_map_insert (decl_map, parm) = clone_parm;
349 clone_parm = TREE_CHAIN (clone_parm);
350 }
351 /* Otherwise, map the VTT parameter to `NULL'. */
352 else
353 *pointer_map_insert (decl_map, parm)
354 = fold_convert (TREE_TYPE (parm), null_pointer_node);
355 }
356 /* Map other parameters to their equivalents in the cloned
357 function. */
358 else
359 {
360 *pointer_map_insert (decl_map, parm) = clone_parm;
361 clone_parm = TREE_CHAIN (clone_parm);
362 }
363 }
364
365 if (targetm.cxx.cdtor_returns_this ())
366 {
367 parm = DECL_RESULT (fn);
368 clone_parm = DECL_RESULT (clone);
369 *pointer_map_insert (decl_map, parm) = clone_parm;
370 }
371
372 /* Clone the body. */
373 clone_body (clone, fn, decl_map);
374
375 /* Clean up. */
376 pointer_map_destroy (decl_map);
377 }
378
379 /* The clone can throw iff the original function can throw. */
380 cp_function_chain->can_throw = !TREE_NOTHROW (fn);
381
382 /* Now, expand this function into RTL, if appropriate. */
383 finish_function (0);
384 BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn);
385 if (alias)
386 expand_or_defer_fn_1 (clone);
387 else
388 expand_or_defer_fn (clone);
389 first = false;
390 }
391 pop_from_top_level ();
392
393 if (comdat_group)
394 {
395 DECL_COMDAT_GROUP (fns[1]) = comdat_group;
396 if (fns[2])
397 /* If *[CD][12]* dtors go into the *[CD]5* comdat group and dtor is
398 virtual, it goes into the same comdat group as well. */
399 DECL_COMDAT_GROUP (fns[2]) = comdat_group;
400 }
401
402 /* We don't need to process the original function any further. */
403 return 1;
404 }