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"
38 #include "tree-inline.h"
40 #include "langhooks.h"
41 #include "diagnostic.h"
42 #include "tree-dump.h"
44 #include "tree-iterator.h"
49 static void update_cloned_parm (tree, tree, bool);
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. */
57 update_cloned_parm (tree parm, tree cloned_parm, bool first)
59 DECL_ABSTRACT_ORIGIN (cloned_parm) = parm;
61 /* We may have taken its address. */
62 TREE_ADDRESSABLE (cloned_parm) = TREE_ADDRESSABLE (parm);
64 /* The definition might have different constness. */
65 TREE_READONLY (cloned_parm) = TREE_READONLY (parm);
67 TREE_USED (cloned_parm) = !first || TREE_USED (parm);
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);
74 DECL_GIMPLE_REG_P (cloned_parm) = DECL_GIMPLE_REG_P (parm);
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. */
83 clone_body (tree clone, tree fn, void *arg_map)
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));
93 id.src_cfun = DECL_STRUCT_FUNCTION (fn);
94 id.decl_map = (struct pointer_map_t *) arg_map;
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;
102 /* We're not inside any EH region. */
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));
110 /* DELETE_DTOR is a delete destructor whose body will be built.
111 COMPLETE_DTOR is the corresponding complete destructor. */
114 build_delete_destructor_body (tree delete_dtor, tree complete_dtor)
116 tree call_dtor, call_delete;
117 tree parm = DECL_ARGUMENTS (delete_dtor);
118 tree virtual_size = cxx_sizeof (current_class_type);
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);
125 add_stmt (build_stmt (0, LABEL_EXPR, cdtor_label));
127 /* Call the delete function. */
128 call_delete = build_op_delete_call (DELETE_EXPR, current_class_ptr,
131 /*placement=*/NULL_TREE,
132 /*alloc_fn=*/NULL_TREE);
133 add_stmt (call_delete);
135 /* Return the address of the object. */
136 if (targetm.cxx.cdtor_returns_this ())
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));
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. */
150 cdtor_comdat_group (tree complete, tree base)
152 tree complete_name = DECL_COMDAT_GROUP (complete);
153 tree base_name = DECL_COMDAT_GROUP (base);
156 bool diff_seen = false;
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];
172 gcc_assert (!diff_seen
174 && (p[idx - 1] == 'C' || p[idx - 1] == 'D')
180 grp_name[idx] = '\0';
181 gcc_assert (diff_seen);
182 return get_identifier (grp_name);
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. */
190 maybe_clone_body (tree fn)
192 tree comdat_group = NULL_TREE;
196 bool in_charge_parm_used;
199 /* We only clone constructors and destructors. */
200 if (!DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn)
201 && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn))
204 /* Emit the DWARF1 abstract instance. */
205 (*debug_hooks->deferred_inline_function) (fn);
207 in_charge_parm_used = CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fn)) != NULL;
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)
218 else if (DECL_NAME (clone) == base_dtor_identifier
219 || DECL_NAME (clone) == base_ctor_identifier)
221 else if (DECL_NAME (clone) == deleting_dtor_identifier)
226 /* We know that any clones immediately follow FN in the TYPE_METHODS
228 push_to_top_level ();
229 for (idx = 0; idx < 3; idx++)
235 struct pointer_map_t *decl_map;
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);
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);
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);
278 parm = TREE_CHAIN (parm), clone_parm = TREE_CHAIN (clone_parm))
279 /* Update this parameter. */
280 update_cloned_parm (parm, clone_parm, first);
282 /* Start processing the function. */
283 start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED);
285 /* Tell cgraph if both ctors or both dtors are known to have
287 if (!in_charge_parm_used
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]))
304 if (DECL_ONE_ONLY (fns[0]))
306 /* For comdat base and complete cdtors put them
307 into the same, *[CD]5* comdat group instead of
309 comdat_group = cdtor_comdat_group (fns[1], fns[0]);
310 DECL_COMDAT_GROUP (fns[0]) = comdat_group;
314 /* Build the delete destructor by calling complete destructor
315 and delete function. */
317 build_delete_destructor_body (clone, fns[1]);
319 /* No need to populate body. */ ;
322 /* Remap the parameters. */
323 decl_map = pointer_map_create ();
325 parm = DECL_ARGUMENTS (fn),
326 clone_parm = DECL_ARGUMENTS (clone);
329 parm = TREE_CHAIN (parm))
331 /* Map the in-charge parameter to an appropriate constant. */
332 if (DECL_HAS_IN_CHARGE_PARM_P (fn) && parmno == 1)
335 in_charge = in_charge_arg_for_name (DECL_NAME (clone));
336 *pointer_map_insert (decl_map, parm) = in_charge;
338 else if (DECL_ARTIFICIAL (parm)
339 && DECL_NAME (parm) == vtt_parm_identifier)
341 /* For a subobject constructor or destructor, the next
342 argument is the VTT parameter. Remap the VTT_PARM
343 from the CLONE to this parameter. */
344 if (DECL_HAS_VTT_PARM_P (clone))
346 DECL_ABSTRACT_ORIGIN (clone_parm) = parm;
347 *pointer_map_insert (decl_map, parm) = clone_parm;
348 clone_parm = TREE_CHAIN (clone_parm);
350 /* Otherwise, map the VTT parameter to `NULL'. */
352 *pointer_map_insert (decl_map, parm)
353 = fold_convert (TREE_TYPE (parm), null_pointer_node);
355 /* Map other parameters to their equivalents in the cloned
359 *pointer_map_insert (decl_map, parm) = clone_parm;
360 clone_parm = TREE_CHAIN (clone_parm);
364 if (targetm.cxx.cdtor_returns_this ())
366 parm = DECL_RESULT (fn);
367 clone_parm = DECL_RESULT (clone);
368 *pointer_map_insert (decl_map, parm) = clone_parm;
371 /* Clone the body. */
372 clone_body (clone, fn, decl_map);
375 pointer_map_destroy (decl_map);
378 /* The clone can throw iff the original function can throw. */
379 cp_function_chain->can_throw = !TREE_NOTHROW (fn);
381 /* Now, expand this function into RTL, if appropriate. */
383 BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn);
386 if (expand_or_defer_fn_1 (clone))
387 emit_associated_thunks (clone);
390 expand_or_defer_fn (clone);
393 pop_from_top_level ();
397 DECL_COMDAT_GROUP (fns[1]) = comdat_group;
399 /* If *[CD][12]* dtors go into the *[CD]5* comdat group and dtor is
400 virtual, it goes into the same comdat group as well. */
401 DECL_COMDAT_GROUP (fns[2]) = comdat_group;
404 /* We don't need to process the original function any further. */