1 /* Perform optimizations on tree structure.
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2007, 2008, 2009,
3 2010 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"
33 #include "tree-inline.h"
35 #include "langhooks.h"
36 #include "diagnostic-core.h"
37 #include "tree-dump.h"
39 #include "tree-iterator.h"
44 static void update_cloned_parm (tree
, tree
, bool);
46 /* CLONED_PARM is a copy of CLONE, generated for a cloned constructor
47 or destructor. Update it to ensure that the source-position for
48 the cloned parameter matches that for the original, and that the
49 debugging generation code will be able to find the original PARM. */
52 update_cloned_parm (tree parm
, tree cloned_parm
, bool first
)
54 DECL_ABSTRACT_ORIGIN (cloned_parm
) = parm
;
56 /* We may have taken its address. */
57 TREE_ADDRESSABLE (cloned_parm
) = TREE_ADDRESSABLE (parm
);
59 /* The definition might have different constness. */
60 TREE_READONLY (cloned_parm
) = TREE_READONLY (parm
);
62 TREE_USED (cloned_parm
) = !first
|| TREE_USED (parm
);
64 /* The name may have changed from the declaration. */
65 DECL_NAME (cloned_parm
) = DECL_NAME (parm
);
66 DECL_SOURCE_LOCATION (cloned_parm
) = DECL_SOURCE_LOCATION (parm
);
67 TREE_TYPE (cloned_parm
) = TREE_TYPE (parm
);
69 DECL_GIMPLE_REG_P (cloned_parm
) = DECL_GIMPLE_REG_P (parm
);
73 /* FN is a function in High GIMPLE form that has a complete body and no
74 CFG. CLONE is a function whose body is to be set to a copy of FN,
75 mapping argument declarations according to the ARG_MAP splay_tree. */
78 clone_body (tree clone
, tree fn
, void *arg_map
)
83 /* Clone the body, as if we were making an inline call. But, remap
84 the parameters in the callee to the parameters of caller. */
85 memset (&id
, 0, sizeof (id
));
88 id
.src_cfun
= DECL_STRUCT_FUNCTION (fn
);
89 id
.decl_map
= (struct pointer_map_t
*) arg_map
;
91 id
.copy_decl
= copy_decl_no_change
;
92 id
.transform_call_graph_edges
= CB_CGE_DUPLICATE
;
93 id
.transform_new_cfg
= true;
94 id
.transform_return_to_modify
= false;
95 id
.transform_lang_insert_block
= NULL
;
97 /* We're not inside any EH region. */
100 stmts
= DECL_SAVED_TREE (fn
);
101 walk_tree (&stmts
, copy_tree_body_r
, &id
, NULL
);
103 /* Also remap the initializer of any static variables so that they (in
104 particular, any label addresses) correspond to the base variant rather
105 than the abstract one. */
106 if (DECL_NAME (clone
) == base_dtor_identifier
107 || DECL_NAME (clone
) == base_ctor_identifier
)
112 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (fn
), ix
, decl
)
113 walk_tree (&DECL_INITIAL (decl
), copy_tree_body_r
, &id
, NULL
);
116 append_to_statement_list_force (stmts
, &DECL_SAVED_TREE (clone
));
119 /* DELETE_DTOR is a delete destructor whose body will be built.
120 COMPLETE_DTOR is the corresponding complete destructor. */
123 build_delete_destructor_body (tree delete_dtor
, tree complete_dtor
)
125 tree call_dtor
, call_delete
;
126 tree parm
= DECL_ARGUMENTS (delete_dtor
);
127 tree virtual_size
= cxx_sizeof (current_class_type
);
129 /* Call the corresponding complete destructor. */
130 gcc_assert (complete_dtor
);
131 call_dtor
= build_cxx_call (complete_dtor
, 1, &parm
);
132 add_stmt (call_dtor
);
134 add_stmt (build_stmt (0, LABEL_EXPR
, cdtor_label
));
136 /* Call the delete function. */
137 call_delete
= build_op_delete_call (DELETE_EXPR
, current_class_ptr
,
140 /*placement=*/NULL_TREE
,
141 /*alloc_fn=*/NULL_TREE
);
142 add_stmt (call_delete
);
144 /* Return the address of the object. */
145 if (targetm
.cxx
.cdtor_returns_this ())
147 tree val
= DECL_ARGUMENTS (delete_dtor
);
148 val
= build2 (MODIFY_EXPR
, TREE_TYPE (val
),
149 DECL_RESULT (delete_dtor
), val
);
150 add_stmt (build_stmt (0, RETURN_EXPR
, val
));
154 /* Return name of comdat group for complete and base ctor (or dtor)
155 that have the same body. If dtor is virtual, deleting dtor goes
156 into this comdat group as well. */
159 cdtor_comdat_group (tree complete
, tree base
)
161 tree complete_name
= DECL_COMDAT_GROUP (complete
);
162 tree base_name
= DECL_COMDAT_GROUP (base
);
165 bool diff_seen
= false;
167 if (complete_name
== NULL
)
168 complete_name
= cxx_comdat_group (complete
);
169 if (base_name
== NULL
)
170 base_name
= cxx_comdat_group (base
);
171 gcc_assert (IDENTIFIER_LENGTH (complete_name
)
172 == IDENTIFIER_LENGTH (base_name
));
173 grp_name
= XALLOCAVEC (char, IDENTIFIER_LENGTH (complete_name
) + 1);
174 p
= IDENTIFIER_POINTER (complete_name
);
175 q
= IDENTIFIER_POINTER (base_name
);
176 for (idx
= 0; idx
< IDENTIFIER_LENGTH (complete_name
); idx
++)
177 if (p
[idx
] == q
[idx
])
178 grp_name
[idx
] = p
[idx
];
181 gcc_assert (!diff_seen
183 && (p
[idx
- 1] == 'C' || p
[idx
- 1] == 'D')
189 grp_name
[idx
] = '\0';
190 gcc_assert (diff_seen
);
191 return get_identifier (grp_name
);
194 /* FN is a function that has a complete body. Clone the body as
195 necessary. Returns nonzero if there's no longer any need to
196 process the main body. */
199 maybe_clone_body (tree fn
)
201 tree comdat_group
= NULL_TREE
;
205 bool in_charge_parm_used
;
207 bool need_alias
= false;
209 /* We only clone constructors and destructors. */
210 if (!DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn
)
211 && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn
))
214 /* Emit the DWARF1 abstract instance. */
215 (*debug_hooks
->deferred_inline_function
) (fn
);
217 in_charge_parm_used
= CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fn
)) != NULL
;
222 /* Look for the complete destructor which may be used to build the
223 delete destructor. */
224 FOR_EACH_CLONE (clone
, fn
)
225 if (DECL_NAME (clone
) == complete_dtor_identifier
226 || DECL_NAME (clone
) == complete_ctor_identifier
)
228 else if (DECL_NAME (clone
) == base_dtor_identifier
229 || DECL_NAME (clone
) == base_ctor_identifier
)
231 else if (DECL_NAME (clone
) == deleting_dtor_identifier
)
236 /* Remember if we can't have multiple clones for some reason. We need to
237 check this before we remap local static initializers in clone_body. */
238 if (!tree_versionable_function_p (fn
))
241 /* We know that any clones immediately follow FN in the TYPE_METHODS
243 push_to_top_level ();
244 for (idx
= 0; idx
< 3; idx
++)
250 struct pointer_map_t
*decl_map
;
256 /* Update CLONE's source position information to match FN's. */
257 DECL_SOURCE_LOCATION (clone
) = DECL_SOURCE_LOCATION (fn
);
258 DECL_DECLARED_INLINE_P (clone
) = DECL_DECLARED_INLINE_P (fn
);
259 DECL_DECLARED_CONSTEXPR_P (clone
) = DECL_DECLARED_CONSTEXPR_P (fn
);
260 DECL_COMDAT (clone
) = DECL_COMDAT (fn
);
261 DECL_WEAK (clone
) = DECL_WEAK (fn
);
263 /* We don't copy the comdat group from fn to clone because the assembler
264 name of fn was corrupted by write_mangled_name by adding *INTERNAL*
265 to it. By doing so, it also corrupted the comdat group. */
266 if (DECL_ONE_ONLY (fn
))
267 DECL_COMDAT_GROUP (clone
) = cxx_comdat_group (clone
);
268 DECL_SECTION_NAME (clone
) = DECL_SECTION_NAME (fn
);
269 DECL_USE_TEMPLATE (clone
) = DECL_USE_TEMPLATE (fn
);
270 DECL_EXTERNAL (clone
) = DECL_EXTERNAL (fn
);
271 DECL_INTERFACE_KNOWN (clone
) = DECL_INTERFACE_KNOWN (fn
);
272 DECL_NOT_REALLY_EXTERN (clone
) = DECL_NOT_REALLY_EXTERN (fn
);
273 TREE_PUBLIC (clone
) = TREE_PUBLIC (fn
);
274 DECL_VISIBILITY (clone
) = DECL_VISIBILITY (fn
);
275 DECL_VISIBILITY_SPECIFIED (clone
) = DECL_VISIBILITY_SPECIFIED (fn
);
276 DECL_DLLIMPORT_P (clone
) = DECL_DLLIMPORT_P (fn
);
277 DECL_ATTRIBUTES (clone
) = copy_list (DECL_ATTRIBUTES (fn
));
278 DECL_DISREGARD_INLINE_LIMITS (clone
) = DECL_DISREGARD_INLINE_LIMITS (fn
);
280 /* Adjust the parameter names and locations. */
281 parm
= DECL_ARGUMENTS (fn
);
282 clone_parm
= DECL_ARGUMENTS (clone
);
283 /* Update the `this' parameter, which is always first. */
284 update_cloned_parm (parm
, clone_parm
, first
);
285 parm
= DECL_CHAIN (parm
);
286 clone_parm
= DECL_CHAIN (clone_parm
);
287 if (DECL_HAS_IN_CHARGE_PARM_P (fn
))
288 parm
= DECL_CHAIN (parm
);
289 if (DECL_HAS_VTT_PARM_P (fn
))
290 parm
= DECL_CHAIN (parm
);
291 if (DECL_HAS_VTT_PARM_P (clone
))
292 clone_parm
= DECL_CHAIN (clone_parm
);
294 parm
= DECL_CHAIN (parm
), clone_parm
= DECL_CHAIN (clone_parm
))
295 /* Update this parameter. */
296 update_cloned_parm (parm
, clone_parm
, first
);
298 /* Start processing the function. */
299 start_preparsed_function (clone
, NULL_TREE
, SF_PRE_PARSED
);
301 /* Tell cgraph if both ctors or both dtors are known to have
303 if (!in_charge_parm_used
306 && !flag_use_repository
307 && DECL_INTERFACE_KNOWN (fns
[0])
308 && (SUPPORTS_ONE_ONLY
|| !DECL_WEAK (fns
[0]))
309 && (!DECL_ONE_ONLY (fns
[0])
310 || (HAVE_COMDAT_GROUP
311 && DECL_WEAK (fns
[0])))
313 /* Set linkage flags appropriately before
314 cgraph_create_function_alias looks at them. */
315 && expand_or_defer_fn_1 (clone
)
316 && cgraph_same_body_alias (cgraph_get_node (fns
[0]),
320 if (DECL_ONE_ONLY (fns
[0]))
322 /* For comdat base and complete cdtors put them
323 into the same, *[CD]5* comdat group instead of
325 comdat_group
= cdtor_comdat_group (fns
[1], fns
[0]);
326 DECL_COMDAT_GROUP (fns
[0]) = comdat_group
;
327 cgraph_add_to_same_comdat_group (cgraph_get_node (clone
),
328 cgraph_get_node (fns
[0]));
332 /* Build the delete destructor by calling complete destructor
333 and delete function. */
336 build_delete_destructor_body (clone
, fns
[1]);
337 /* If *[CD][12]* dtors go into the *[CD]5* comdat group and dtor is
338 virtual, it goes into the same comdat group as well. */
340 cgraph_add_to_same_comdat_group (cgraph_get_create_node (clone
),
341 cgraph_get_node (fns
[0]));
344 /* No need to populate body. */ ;
347 /* If we can't have multiple copies of FN (say, because there's a
348 static local initialized with the address of a label), we need
349 to use an alias for the complete variant. */
350 if (idx
== 1 && need_alias
)
352 if (DECL_STRUCT_FUNCTION (fn
)->cannot_be_copied_set
)
353 sorry (DECL_STRUCT_FUNCTION (fn
)->cannot_be_copied_reason
, fn
);
355 sorry ("making multiple clones of %qD", fn
);
358 /* Remap the parameters. */
359 decl_map
= pointer_map_create ();
361 parm
= DECL_ARGUMENTS (fn
),
362 clone_parm
= DECL_ARGUMENTS (clone
);
365 parm
= DECL_CHAIN (parm
))
367 /* Map the in-charge parameter to an appropriate constant. */
368 if (DECL_HAS_IN_CHARGE_PARM_P (fn
) && parmno
== 1)
371 in_charge
= in_charge_arg_for_name (DECL_NAME (clone
));
372 *pointer_map_insert (decl_map
, parm
) = in_charge
;
374 else if (DECL_ARTIFICIAL (parm
)
375 && DECL_NAME (parm
) == vtt_parm_identifier
)
377 /* For a subobject constructor or destructor, the next
378 argument is the VTT parameter. Remap the VTT_PARM
379 from the CLONE to this parameter. */
380 if (DECL_HAS_VTT_PARM_P (clone
))
382 DECL_ABSTRACT_ORIGIN (clone_parm
) = parm
;
383 *pointer_map_insert (decl_map
, parm
) = clone_parm
;
384 clone_parm
= DECL_CHAIN (clone_parm
);
386 /* Otherwise, map the VTT parameter to `NULL'. */
388 *pointer_map_insert (decl_map
, parm
)
389 = fold_convert (TREE_TYPE (parm
), null_pointer_node
);
391 /* Map other parameters to their equivalents in the cloned
395 *pointer_map_insert (decl_map
, parm
) = clone_parm
;
396 clone_parm
= DECL_CHAIN (clone_parm
);
400 if (targetm
.cxx
.cdtor_returns_this ())
402 parm
= DECL_RESULT (fn
);
403 clone_parm
= DECL_RESULT (clone
);
404 *pointer_map_insert (decl_map
, parm
) = clone_parm
;
407 /* Clone the body. */
408 clone_body (clone
, fn
, decl_map
);
411 pointer_map_destroy (decl_map
);
414 /* The clone can throw iff the original function can throw. */
415 cp_function_chain
->can_throw
= !TREE_NOTHROW (fn
);
417 /* Now, expand this function into RTL, if appropriate. */
419 BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone
)) = DECL_INITIAL (fn
);
422 if (expand_or_defer_fn_1 (clone
))
423 emit_associated_thunks (clone
);
426 expand_or_defer_fn (clone
);
429 pop_from_top_level ();
431 /* We don't need to process the original function any further. */