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).
6 This file is part of GCC.
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)
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.
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/>. */
24 #include "coretypes.h"
29 #include "insn-config.h"
31 #include "integrate.h"
37 #include "tree-inline.h"
39 #include "langhooks.h"
40 #include "diagnostic.h"
41 #include "tree-dump.h"
43 #include "tree-iterator.h"
48 static void update_cloned_parm (tree, tree, bool);
50 /* CLONED_PARM is a copy of CLONE, generated for a cloned constructor
51 or destructor. Update it to ensure that the source-position for
52 the cloned parameter matches that for the original, and that the
53 debugging generation code will be able to find the original PARM. */
56 update_cloned_parm (tree parm, tree cloned_parm, bool first)
58 DECL_ABSTRACT_ORIGIN (cloned_parm) = parm;
60 /* We may have taken its address. */
61 TREE_ADDRESSABLE (cloned_parm) = TREE_ADDRESSABLE (parm);
63 /* The definition might have different constness. */
64 TREE_READONLY (cloned_parm) = TREE_READONLY (parm);
66 TREE_USED (cloned_parm) = !first || TREE_USED (parm);
68 /* The name may have changed from the declaration. */
69 DECL_NAME (cloned_parm) = DECL_NAME (parm);
70 DECL_SOURCE_LOCATION (cloned_parm) = DECL_SOURCE_LOCATION (parm);
71 TREE_TYPE (cloned_parm) = TREE_TYPE (parm);
73 DECL_GIMPLE_REG_P (cloned_parm) = DECL_GIMPLE_REG_P (parm);
77 /* FN is a function in High GIMPLE form that has a complete body and no
78 CFG. CLONE is a function whose body is to be set to a copy of FN,
79 mapping argument declarations according to the ARG_MAP splay_tree. */
82 clone_body (tree clone, tree fn, void *arg_map)
87 /* Clone the body, as if we were making an inline call. But, remap
88 the parameters in the callee to the parameters of caller. */
89 memset (&id, 0, sizeof (id));
92 id.src_cfun = DECL_STRUCT_FUNCTION (fn);
93 id.decl_map = (struct pointer_map_t *) arg_map;
95 id.copy_decl = copy_decl_no_change;
96 id.transform_call_graph_edges = CB_CGE_DUPLICATE;
97 id.transform_new_cfg = true;
98 id.transform_return_to_modify = false;
99 id.transform_lang_insert_block = NULL;
101 /* We're not inside any EH region. */
104 stmts = DECL_SAVED_TREE (fn);
105 walk_tree (&stmts, copy_tree_body_r, &id, NULL);
107 /* Also remap the initializer of any static variables so that they (in
108 particular, any label addresses) correspond to the base variant rather
109 than the abstract one. */
110 if (DECL_NAME (clone) == base_dtor_identifier
111 || DECL_NAME (clone) == base_ctor_identifier)
113 tree decls = DECL_STRUCT_FUNCTION (fn)->local_decls;
114 for (; decls; decls = TREE_CHAIN (decls))
116 tree decl = TREE_VALUE (decls);
117 walk_tree (&DECL_INITIAL (decl), copy_tree_body_r, &id, NULL);
121 append_to_statement_list_force (stmts, &DECL_SAVED_TREE (clone));
124 /* DELETE_DTOR is a delete destructor whose body will be built.
125 COMPLETE_DTOR is the corresponding complete destructor. */
128 build_delete_destructor_body (tree delete_dtor, tree complete_dtor)
130 tree call_dtor, call_delete;
131 tree parm = DECL_ARGUMENTS (delete_dtor);
132 tree virtual_size = cxx_sizeof (current_class_type);
134 /* Call the corresponding complete destructor. */
135 gcc_assert (complete_dtor);
136 call_dtor = build_cxx_call (complete_dtor, 1, &parm);
137 add_stmt (call_dtor);
139 add_stmt (build_stmt (0, LABEL_EXPR, cdtor_label));
141 /* Call the delete function. */
142 call_delete = build_op_delete_call (DELETE_EXPR, current_class_ptr,
145 /*placement=*/NULL_TREE,
146 /*alloc_fn=*/NULL_TREE);
147 add_stmt (call_delete);
149 /* Return the address of the object. */
150 if (targetm.cxx.cdtor_returns_this ())
152 tree val = DECL_ARGUMENTS (delete_dtor);
153 val = build2 (MODIFY_EXPR, TREE_TYPE (val),
154 DECL_RESULT (delete_dtor), val);
155 add_stmt (build_stmt (0, RETURN_EXPR, val));
159 /* Return name of comdat group for complete and base ctor (or dtor)
160 that have the same body. If dtor is virtual, deleting dtor goes
161 into this comdat group as well. */
164 cdtor_comdat_group (tree complete, tree base)
166 tree complete_name = DECL_COMDAT_GROUP (complete);
167 tree base_name = DECL_COMDAT_GROUP (base);
170 bool diff_seen = false;
172 if (complete_name == NULL)
173 complete_name = cxx_comdat_group (complete);
174 if (base_name == NULL)
175 base_name = cxx_comdat_group (base);
176 gcc_assert (IDENTIFIER_LENGTH (complete_name)
177 == IDENTIFIER_LENGTH (base_name));
178 grp_name = XALLOCAVEC (char, IDENTIFIER_LENGTH (complete_name) + 1);
179 p = IDENTIFIER_POINTER (complete_name);
180 q = IDENTIFIER_POINTER (base_name);
181 for (idx = 0; idx < IDENTIFIER_LENGTH (complete_name); idx++)
182 if (p[idx] == q[idx])
183 grp_name[idx] = p[idx];
186 gcc_assert (!diff_seen
188 && (p[idx - 1] == 'C' || p[idx - 1] == 'D')
194 grp_name[idx] = '\0';
195 gcc_assert (diff_seen);
196 return get_identifier (grp_name);
199 /* FN is a function that has a complete body. Clone the body as
200 necessary. Returns nonzero if there's no longer any need to
201 process the main body. */
204 maybe_clone_body (tree fn)
206 tree comdat_group = NULL_TREE;
210 bool in_charge_parm_used;
212 bool need_alias = false;
214 /* We only clone constructors and destructors. */
215 if (!DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn)
216 && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn))
219 /* Emit the DWARF1 abstract instance. */
220 (*debug_hooks->deferred_inline_function) (fn);
222 in_charge_parm_used = CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fn)) != NULL;
227 /* Look for the complete destructor which may be used to build the
228 delete destructor. */
229 FOR_EACH_CLONE (clone, fn)
230 if (DECL_NAME (clone) == complete_dtor_identifier
231 || DECL_NAME (clone) == complete_ctor_identifier)
233 else if (DECL_NAME (clone) == base_dtor_identifier
234 || DECL_NAME (clone) == base_ctor_identifier)
236 else if (DECL_NAME (clone) == deleting_dtor_identifier)
241 /* Remember if we can't have multiple clones for some reason. We need to
242 check this before we remap local static initializers in clone_body. */
243 if (!tree_versionable_function_p (fn))
246 /* We know that any clones immediately follow FN in the TYPE_METHODS
248 push_to_top_level ();
249 for (idx = 0; idx < 3; idx++)
255 struct pointer_map_t *decl_map;
261 /* Update CLONE's source position information to match FN's. */
262 DECL_SOURCE_LOCATION (clone) = DECL_SOURCE_LOCATION (fn);
263 DECL_DECLARED_INLINE_P (clone) = DECL_DECLARED_INLINE_P (fn);
264 DECL_COMDAT (clone) = DECL_COMDAT (fn);
265 DECL_WEAK (clone) = DECL_WEAK (fn);
267 /* We don't copy the comdat group from fn to clone because the assembler
268 name of fn was corrupted by write_mangled_name by adding *INTERNAL*
269 to it. By doing so, it also corrupted the comdat group. */
270 if (DECL_ONE_ONLY (fn))
271 DECL_COMDAT_GROUP (clone) = cxx_comdat_group (clone);
272 DECL_SECTION_NAME (clone) = DECL_SECTION_NAME (fn);
273 DECL_USE_TEMPLATE (clone) = DECL_USE_TEMPLATE (fn);
274 DECL_EXTERNAL (clone) = DECL_EXTERNAL (fn);
275 DECL_INTERFACE_KNOWN (clone) = DECL_INTERFACE_KNOWN (fn);
276 DECL_NOT_REALLY_EXTERN (clone) = DECL_NOT_REALLY_EXTERN (fn);
277 TREE_PUBLIC (clone) = TREE_PUBLIC (fn);
278 DECL_VISIBILITY (clone) = DECL_VISIBILITY (fn);
279 DECL_VISIBILITY_SPECIFIED (clone) = DECL_VISIBILITY_SPECIFIED (fn);
280 DECL_DLLIMPORT_P (clone) = DECL_DLLIMPORT_P (fn);
281 DECL_ATTRIBUTES (clone) = copy_list (DECL_ATTRIBUTES (fn));
282 DECL_DISREGARD_INLINE_LIMITS (clone) = DECL_DISREGARD_INLINE_LIMITS (fn);
284 /* Adjust the parameter names and locations. */
285 parm = DECL_ARGUMENTS (fn);
286 clone_parm = DECL_ARGUMENTS (clone);
287 /* Update the `this' parameter, which is always first. */
288 update_cloned_parm (parm, clone_parm, first);
289 parm = TREE_CHAIN (parm);
290 clone_parm = TREE_CHAIN (clone_parm);
291 if (DECL_HAS_IN_CHARGE_PARM_P (fn))
292 parm = TREE_CHAIN (parm);
293 if (DECL_HAS_VTT_PARM_P (fn))
294 parm = TREE_CHAIN (parm);
295 if (DECL_HAS_VTT_PARM_P (clone))
296 clone_parm = TREE_CHAIN (clone_parm);
298 parm = TREE_CHAIN (parm), clone_parm = TREE_CHAIN (clone_parm))
299 /* Update this parameter. */
300 update_cloned_parm (parm, clone_parm, first);
302 /* Start processing the function. */
303 start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED);
305 /* Tell cgraph if both ctors or both dtors are known to have
307 if (!in_charge_parm_used
310 && !flag_use_repository
311 && DECL_INTERFACE_KNOWN (fns[0])
312 && (SUPPORTS_ONE_ONLY || !DECL_WEAK (fns[0]))
313 && (!DECL_ONE_ONLY (fns[0])
314 || (HAVE_COMDAT_GROUP
315 && DECL_WEAK (fns[0])))
316 && cgraph_same_body_alias (clone, fns[0]))
319 if (DECL_ONE_ONLY (fns[0]))
321 /* For comdat base and complete cdtors put them
322 into the same, *[CD]5* comdat group instead of
324 comdat_group = cdtor_comdat_group (fns[1], fns[0]);
325 DECL_COMDAT_GROUP (fns[0]) = comdat_group;
329 /* Build the delete destructor by calling complete destructor
330 and delete function. */
332 build_delete_destructor_body (clone, fns[1]);
334 /* No need to populate body. */ ;
337 /* If we can't have multiple copies of FN (say, because there's a
338 static local initialized with the address of a label), we need
339 to use an alias for the complete variant. */
340 if (idx == 1 && need_alias)
342 if (DECL_STRUCT_FUNCTION (fn)->cannot_be_copied_set)
343 sorry (DECL_STRUCT_FUNCTION (fn)->cannot_be_copied_reason, fn);
345 sorry ("making multiple clones of %qD", fn);
348 /* Remap the parameters. */
349 decl_map = pointer_map_create ();
351 parm = DECL_ARGUMENTS (fn),
352 clone_parm = DECL_ARGUMENTS (clone);
355 parm = TREE_CHAIN (parm))
357 /* Map the in-charge parameter to an appropriate constant. */
358 if (DECL_HAS_IN_CHARGE_PARM_P (fn) && parmno == 1)
361 in_charge = in_charge_arg_for_name (DECL_NAME (clone));
362 *pointer_map_insert (decl_map, parm) = in_charge;
364 else if (DECL_ARTIFICIAL (parm)
365 && DECL_NAME (parm) == vtt_parm_identifier)
367 /* For a subobject constructor or destructor, the next
368 argument is the VTT parameter. Remap the VTT_PARM
369 from the CLONE to this parameter. */
370 if (DECL_HAS_VTT_PARM_P (clone))
372 DECL_ABSTRACT_ORIGIN (clone_parm) = parm;
373 *pointer_map_insert (decl_map, parm) = clone_parm;
374 clone_parm = TREE_CHAIN (clone_parm);
376 /* Otherwise, map the VTT parameter to `NULL'. */
378 *pointer_map_insert (decl_map, parm)
379 = fold_convert (TREE_TYPE (parm), null_pointer_node);
381 /* Map other parameters to their equivalents in the cloned
385 *pointer_map_insert (decl_map, parm) = clone_parm;
386 clone_parm = TREE_CHAIN (clone_parm);
390 if (targetm.cxx.cdtor_returns_this ())
392 parm = DECL_RESULT (fn);
393 clone_parm = DECL_RESULT (clone);
394 *pointer_map_insert (decl_map, parm) = clone_parm;
397 /* Clone the body. */
398 clone_body (clone, fn, decl_map);
401 pointer_map_destroy (decl_map);
404 /* The clone can throw iff the original function can throw. */
405 cp_function_chain->can_throw = !TREE_NOTHROW (fn);
407 /* Now, expand this function into RTL, if appropriate. */
409 BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn);
412 if (expand_or_defer_fn_1 (clone))
413 emit_associated_thunks (clone);
416 expand_or_defer_fn (clone);
419 pop_from_top_level ();
423 DECL_COMDAT_GROUP (fns[1]) = comdat_group;
426 struct cgraph_node *base_dtor_node, *deleting_dtor_node;
427 /* If *[CD][12]* dtors go into the *[CD]5* comdat group and dtor is
428 virtual, it goes into the same comdat group as well. */
429 DECL_COMDAT_GROUP (fns[2]) = comdat_group;
430 base_dtor_node = cgraph_node (fns[0]);
431 deleting_dtor_node = cgraph_node (fns[2]);
432 gcc_assert (base_dtor_node->same_comdat_group == NULL);
433 gcc_assert (deleting_dtor_node->same_comdat_group == NULL);
434 base_dtor_node->same_comdat_group = deleting_dtor_node;
435 deleting_dtor_node->same_comdat_group = base_dtor_node;
439 /* We don't need to process the original function any further. */