OSDN Git Service

* cgraph.c (same_body_alias_1): Break out of
[pf3gnuchains/gcc-fork.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 /* FN is a function that has a complete body.  Clone the body as
146    necessary.  Returns nonzero if there's no longer any need to
147    process the main body.  */
148
149 bool
150 maybe_clone_body (tree fn)
151 {
152   tree clone;
153   tree fns[3];
154   bool first = true;
155   bool in_charge_parm_used;
156   int idx;
157
158   /* We only clone constructors and destructors.  */
159   if (!DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn)
160       && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn))
161     return 0;
162
163   /* Emit the DWARF1 abstract instance.  */
164   (*debug_hooks->deferred_inline_function) (fn);
165
166   in_charge_parm_used = CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fn)) != NULL;
167   fns[0] = NULL_TREE;
168   fns[1] = NULL_TREE;
169   fns[2] = NULL_TREE;
170
171   /* Look for the complete destructor which may be used to build the
172      delete destructor.  */
173   FOR_EACH_CLONE (clone, fn)
174     if (DECL_NAME (clone) == complete_dtor_identifier
175         || DECL_NAME (clone) == complete_ctor_identifier)
176       fns[1] = clone;
177     else if (DECL_NAME (clone) == base_dtor_identifier
178              || DECL_NAME (clone) == base_ctor_identifier)
179       fns[0] = clone;
180     else if (DECL_NAME (clone) == deleting_dtor_identifier)
181       fns[2] = clone;
182     else
183       gcc_unreachable ();
184
185   /* We know that any clones immediately follow FN in the TYPE_METHODS
186      list.  */
187   push_to_top_level ();
188   for (idx = 0; idx < 3; idx++)
189     {
190       tree parm;
191       tree clone_parm;
192       int parmno;
193       bool alias = false;
194       struct pointer_map_t *decl_map;
195
196       clone = fns[idx];
197       if (!clone)
198         continue;      
199
200       /* Update CLONE's source position information to match FN's.  */
201       DECL_SOURCE_LOCATION (clone) = DECL_SOURCE_LOCATION (fn);
202       DECL_DECLARED_INLINE_P (clone) = DECL_DECLARED_INLINE_P (fn);
203       DECL_COMDAT (clone) = DECL_COMDAT (fn);
204       DECL_WEAK (clone) = DECL_WEAK (fn);
205
206       /* We don't copy the comdat group from fn to clone because the assembler
207          name of fn was corrupted by write_mangled_name by adding *INTERNAL*
208          to it. By doing so, it also corrupted the comdat group. */
209       if (DECL_ONE_ONLY (fn))
210         DECL_COMDAT_GROUP (clone) = cxx_comdat_group (clone);
211       DECL_SECTION_NAME (clone) = DECL_SECTION_NAME (fn);
212       DECL_USE_TEMPLATE (clone) = DECL_USE_TEMPLATE (fn);
213       DECL_EXTERNAL (clone) = DECL_EXTERNAL (fn);
214       DECL_INTERFACE_KNOWN (clone) = DECL_INTERFACE_KNOWN (fn);
215       DECL_NOT_REALLY_EXTERN (clone) = DECL_NOT_REALLY_EXTERN (fn);
216       TREE_PUBLIC (clone) = TREE_PUBLIC (fn);
217       DECL_VISIBILITY (clone) = DECL_VISIBILITY (fn);
218       DECL_VISIBILITY_SPECIFIED (clone) = DECL_VISIBILITY_SPECIFIED (fn);
219       DECL_DLLIMPORT_P (clone) = DECL_DLLIMPORT_P (fn);
220       DECL_ATTRIBUTES (clone) = copy_list (DECL_ATTRIBUTES (fn));
221       DECL_DISREGARD_INLINE_LIMITS (clone) = DECL_DISREGARD_INLINE_LIMITS (fn);
222
223       /* Adjust the parameter names and locations.  */
224       parm = DECL_ARGUMENTS (fn);
225       clone_parm = DECL_ARGUMENTS (clone);
226       /* Update the `this' parameter, which is always first.  */
227       update_cloned_parm (parm, clone_parm, first);
228       parm = TREE_CHAIN (parm);
229       clone_parm = TREE_CHAIN (clone_parm);
230       if (DECL_HAS_IN_CHARGE_PARM_P (fn))
231         parm = TREE_CHAIN (parm);
232       if (DECL_HAS_VTT_PARM_P (fn))
233         parm = TREE_CHAIN (parm);
234       if (DECL_HAS_VTT_PARM_P (clone))
235         clone_parm = TREE_CHAIN (clone_parm);
236       for (; parm;
237            parm = TREE_CHAIN (parm), clone_parm = TREE_CHAIN (clone_parm))
238         /* Update this parameter.  */
239         update_cloned_parm (parm, clone_parm, first);
240
241       /* Start processing the function.  */
242       start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED);
243
244       /* Tell cgraph if both ctors or both dtors are known to have
245          the same body.  */
246       if (!in_charge_parm_used
247           && fns[0]
248           && idx == 1
249           && !flag_use_repository
250           && DECL_INTERFACE_KNOWN (fns[0])
251           && !DECL_ONE_ONLY (fns[0])
252           && cgraph_same_body_alias (clone, fns[0]))
253         {
254           alias = true;
255           emit_associated_thunks (clone);
256         }
257
258       /* Build the delete destructor by calling complete destructor
259          and delete function.  */
260       if (idx == 2)
261         build_delete_destructor_body (clone, fns[1]);
262       else if (alias)
263         /* No need to populate body.  */ ;
264       else
265         {
266           /* Remap the parameters.  */
267           decl_map = pointer_map_create ();
268           for (parmno = 0,
269                 parm = DECL_ARGUMENTS (fn),
270                 clone_parm = DECL_ARGUMENTS (clone);
271               parm;
272               ++parmno,
273                 parm = TREE_CHAIN (parm))
274             {
275               /* Map the in-charge parameter to an appropriate constant.  */
276               if (DECL_HAS_IN_CHARGE_PARM_P (fn) && parmno == 1)
277                 {
278                   tree in_charge;
279                   in_charge = in_charge_arg_for_name (DECL_NAME (clone));
280                   *pointer_map_insert (decl_map, parm) = in_charge;
281                 }
282               else if (DECL_ARTIFICIAL (parm)
283                        && DECL_NAME (parm) == vtt_parm_identifier)
284                 {
285                   /* For a subobject constructor or destructor, the next
286                      argument is the VTT parameter.  Remap the VTT_PARM
287                      from the CLONE to this parameter.  */
288                   if (DECL_HAS_VTT_PARM_P (clone))
289                     {
290                       DECL_ABSTRACT_ORIGIN (clone_parm) = parm;
291                       *pointer_map_insert (decl_map, parm) = clone_parm;
292                       clone_parm = TREE_CHAIN (clone_parm);
293                     }
294                   /* Otherwise, map the VTT parameter to `NULL'.  */
295                   else
296                     *pointer_map_insert (decl_map, parm)
297                        = fold_convert (TREE_TYPE (parm), null_pointer_node);
298                 }
299               /* Map other parameters to their equivalents in the cloned
300                  function.  */
301               else
302                 {
303                   *pointer_map_insert (decl_map, parm) = clone_parm;
304                   clone_parm = TREE_CHAIN (clone_parm);
305                 }
306             }
307
308           if (targetm.cxx.cdtor_returns_this ())
309             {
310               parm = DECL_RESULT (fn);
311               clone_parm = DECL_RESULT (clone);
312               *pointer_map_insert (decl_map, parm) = clone_parm;
313             }
314
315           /* Clone the body.  */
316           clone_body (clone, fn, decl_map);
317
318           /* Clean up.  */
319           pointer_map_destroy (decl_map);
320         }
321
322       /* The clone can throw iff the original function can throw.  */
323       cp_function_chain->can_throw = !TREE_NOTHROW (fn);
324
325       /* Now, expand this function into RTL, if appropriate.  */
326       finish_function (0);
327       BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn);
328       if (alias)
329         expand_or_defer_fn_1 (clone);
330       else
331         expand_or_defer_fn (clone);
332       first = false;
333     }
334   pop_from_top_level ();
335
336   /* We don't need to process the original function any further.  */
337   return 1;
338 }