xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/cp/optimize.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
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 
108   /* Also remap the initializer of any static variables so that they (in
109      particular, any label addresses) correspond to the base variant rather
110      than the abstract one.  */
111   if (DECL_NAME (clone) == base_dtor_identifier
112       || DECL_NAME (clone) == base_ctor_identifier)
113     {
114       tree decls = DECL_STRUCT_FUNCTION (fn)->local_decls;
115       for (; decls; decls = TREE_CHAIN (decls))
116 	{
117 	  tree decl = TREE_VALUE (decls);
118 	  walk_tree (&DECL_INITIAL (decl), copy_tree_body_r, &id, NULL);
119 	}
120     }
121 
122   append_to_statement_list_force (stmts, &DECL_SAVED_TREE (clone));
123 }
124 
125 /* DELETE_DTOR is a delete destructor whose body will be built.
126    COMPLETE_DTOR is the corresponding complete destructor.  */
127 
128 static void
129 build_delete_destructor_body (tree delete_dtor, tree complete_dtor)
130 {
131   tree call_dtor, call_delete;
132   tree parm = DECL_ARGUMENTS (delete_dtor);
133   tree virtual_size = cxx_sizeof (current_class_type);
134 
135   /* Call the corresponding complete destructor.  */
136   gcc_assert (complete_dtor);
137   call_dtor = build_cxx_call (complete_dtor, 1, &parm);
138   add_stmt (call_dtor);
139 
140   add_stmt (build_stmt (0, LABEL_EXPR, cdtor_label));
141 
142   /* Call the delete function.  */
143   call_delete = build_op_delete_call (DELETE_EXPR, current_class_ptr,
144                                       virtual_size,
145                                       /*global_p=*/false,
146                                       /*placement=*/NULL_TREE,
147                                       /*alloc_fn=*/NULL_TREE);
148   add_stmt (call_delete);
149 
150   /* Return the address of the object.  */
151   if (targetm.cxx.cdtor_returns_this ())
152     {
153       tree val = DECL_ARGUMENTS (delete_dtor);
154       val = build2 (MODIFY_EXPR, TREE_TYPE (val),
155                     DECL_RESULT (delete_dtor), val);
156       add_stmt (build_stmt (0, RETURN_EXPR, val));
157     }
158 }
159 
160 /* Return name of comdat group for complete and base ctor (or dtor)
161    that have the same body.  If dtor is virtual, deleting dtor goes
162    into this comdat group as well.  */
163 
164 static tree
165 cdtor_comdat_group (tree complete, tree base)
166 {
167   tree complete_name = DECL_COMDAT_GROUP (complete);
168   tree base_name = DECL_COMDAT_GROUP (base);
169   char *grp_name;
170   const char *p, *q;
171   bool diff_seen = false;
172   size_t idx;
173   if (complete_name == NULL)
174     complete_name = cxx_comdat_group (complete);
175   if (base_name == NULL)
176     base_name = cxx_comdat_group (base);
177   gcc_assert (IDENTIFIER_LENGTH (complete_name)
178 	      == IDENTIFIER_LENGTH (base_name));
179   grp_name = XALLOCAVEC (char, IDENTIFIER_LENGTH (complete_name) + 1);
180   p = IDENTIFIER_POINTER (complete_name);
181   q = IDENTIFIER_POINTER (base_name);
182   for (idx = 0; idx < IDENTIFIER_LENGTH (complete_name); idx++)
183     if (p[idx] == q[idx])
184       grp_name[idx] = p[idx];
185     else
186       {
187 	gcc_assert (!diff_seen
188 		    && idx > 0
189 		    && (p[idx - 1] == 'C' || p[idx - 1] == 'D')
190 		    && p[idx] == '1'
191 		    && q[idx] == '2');
192 	grp_name[idx] = '5';
193 	diff_seen = true;
194       }
195   grp_name[idx] = '\0';
196   gcc_assert (diff_seen);
197   return get_identifier (grp_name);
198 }
199 
200 /* FN is a function that has a complete body.  Clone the body as
201    necessary.  Returns nonzero if there's no longer any need to
202    process the main body.  */
203 
204 bool
205 maybe_clone_body (tree fn)
206 {
207   tree comdat_group = NULL_TREE;
208   tree clone;
209   tree fns[3];
210   bool first = true;
211   bool in_charge_parm_used;
212   int idx;
213   bool need_alias = false;
214 
215   /* We only clone constructors and destructors.  */
216   if (!DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn)
217       && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn))
218     return 0;
219 
220   /* Emit the DWARF1 abstract instance.  */
221   (*debug_hooks->deferred_inline_function) (fn);
222 
223   in_charge_parm_used = CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fn)) != NULL;
224   fns[0] = NULL_TREE;
225   fns[1] = NULL_TREE;
226   fns[2] = NULL_TREE;
227 
228   /* Look for the complete destructor which may be used to build the
229      delete destructor.  */
230   FOR_EACH_CLONE (clone, fn)
231     if (DECL_NAME (clone) == complete_dtor_identifier
232 	|| DECL_NAME (clone) == complete_ctor_identifier)
233       fns[1] = clone;
234     else if (DECL_NAME (clone) == base_dtor_identifier
235 	     || DECL_NAME (clone) == base_ctor_identifier)
236       fns[0] = clone;
237     else if (DECL_NAME (clone) == deleting_dtor_identifier)
238       fns[2] = clone;
239     else
240       gcc_unreachable ();
241 
242   /* Remember if we can't have multiple clones for some reason.  We need to
243      check this before we remap local static initializers in clone_body.  */
244   if (!tree_versionable_function_p (fn))
245     need_alias = true;
246 
247   /* We know that any clones immediately follow FN in the TYPE_METHODS
248      list.  */
249   push_to_top_level ();
250   for (idx = 0; idx < 3; idx++)
251     {
252       tree parm;
253       tree clone_parm;
254       int parmno;
255       bool alias = false;
256       struct pointer_map_t *decl_map;
257 
258       clone = fns[idx];
259       if (!clone)
260 	continue;
261 
262       /* Update CLONE's source position information to match FN's.  */
263       DECL_SOURCE_LOCATION (clone) = DECL_SOURCE_LOCATION (fn);
264       DECL_DECLARED_INLINE_P (clone) = DECL_DECLARED_INLINE_P (fn);
265       DECL_COMDAT (clone) = DECL_COMDAT (fn);
266       DECL_WEAK (clone) = DECL_WEAK (fn);
267 
268       /* We don't copy the comdat group from fn to clone because the assembler
269 	 name of fn was corrupted by write_mangled_name by adding *INTERNAL*
270 	 to it. By doing so, it also corrupted the comdat group. */
271       if (DECL_ONE_ONLY (fn))
272 	DECL_COMDAT_GROUP (clone) = cxx_comdat_group (clone);
273       DECL_SECTION_NAME (clone) = DECL_SECTION_NAME (fn);
274       DECL_USE_TEMPLATE (clone) = DECL_USE_TEMPLATE (fn);
275       DECL_EXTERNAL (clone) = DECL_EXTERNAL (fn);
276       DECL_INTERFACE_KNOWN (clone) = DECL_INTERFACE_KNOWN (fn);
277       DECL_NOT_REALLY_EXTERN (clone) = DECL_NOT_REALLY_EXTERN (fn);
278       TREE_PUBLIC (clone) = TREE_PUBLIC (fn);
279       DECL_VISIBILITY (clone) = DECL_VISIBILITY (fn);
280       DECL_VISIBILITY_SPECIFIED (clone) = DECL_VISIBILITY_SPECIFIED (fn);
281       DECL_DLLIMPORT_P (clone) = DECL_DLLIMPORT_P (fn);
282       DECL_ATTRIBUTES (clone) = copy_list (DECL_ATTRIBUTES (fn));
283       DECL_DISREGARD_INLINE_LIMITS (clone) = DECL_DISREGARD_INLINE_LIMITS (fn);
284 
285       /* Adjust the parameter names and locations.  */
286       parm = DECL_ARGUMENTS (fn);
287       clone_parm = DECL_ARGUMENTS (clone);
288       /* Update the `this' parameter, which is always first.  */
289       update_cloned_parm (parm, clone_parm, first);
290       parm = TREE_CHAIN (parm);
291       clone_parm = TREE_CHAIN (clone_parm);
292       if (DECL_HAS_IN_CHARGE_PARM_P (fn))
293 	parm = TREE_CHAIN (parm);
294       if (DECL_HAS_VTT_PARM_P (fn))
295 	parm = TREE_CHAIN (parm);
296       if (DECL_HAS_VTT_PARM_P (clone))
297 	clone_parm = TREE_CHAIN (clone_parm);
298       for (; parm;
299 	   parm = TREE_CHAIN (parm), clone_parm = TREE_CHAIN (clone_parm))
300 	/* Update this parameter.  */
301 	update_cloned_parm (parm, clone_parm, first);
302 
303       /* Start processing the function.  */
304       start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED);
305 
306       /* Tell cgraph if both ctors or both dtors are known to have
307 	 the same body.  */
308       if (!in_charge_parm_used
309 	  && fns[0]
310 	  && idx == 1
311 	  && !flag_use_repository
312 	  && DECL_INTERFACE_KNOWN (fns[0])
313 	  && (SUPPORTS_ONE_ONLY || !DECL_WEAK (fns[0]))
314 	  && (!DECL_ONE_ONLY (fns[0])
315 	      || (HAVE_COMDAT_GROUP
316 		  && DECL_WEAK (fns[0])))
317 	  && cgraph_same_body_alias (clone, fns[0]))
318 	{
319 	  alias = true;
320 	  if (DECL_ONE_ONLY (fns[0]))
321 	    {
322 	      /* For comdat base and complete cdtors put them
323 		 into the same, *[CD]5* comdat group instead of
324 		 *[CD][12]*.  */
325 	      comdat_group = cdtor_comdat_group (fns[1], fns[0]);
326 	      DECL_COMDAT_GROUP (fns[0]) = comdat_group;
327 	    }
328 	}
329 
330       /* Build the delete destructor by calling complete destructor
331          and delete function.  */
332       if (idx == 2)
333 	build_delete_destructor_body (clone, fns[1]);
334       else if (alias)
335 	/* No need to populate body.  */ ;
336       else
337 	{
338 	  /* If we can't have multiple copies of FN (say, because there's a
339 	     static local initialized with the address of a label), we need
340 	     to use an alias for the complete variant.  */
341 	  if (idx == 1 && need_alias)
342 	    {
343 	      if (DECL_STRUCT_FUNCTION (fn)->cannot_be_copied_set)
344 		sorry (DECL_STRUCT_FUNCTION (fn)->cannot_be_copied_reason, fn);
345 	      else
346 		sorry ("making multiple clones of %qD", fn);
347 	    }
348 
349           /* Remap the parameters.  */
350           decl_map = pointer_map_create ();
351           for (parmno = 0,
352                 parm = DECL_ARGUMENTS (fn),
353                 clone_parm = DECL_ARGUMENTS (clone);
354               parm;
355               ++parmno,
356                 parm = TREE_CHAIN (parm))
357             {
358               /* Map the in-charge parameter to an appropriate constant.  */
359               if (DECL_HAS_IN_CHARGE_PARM_P (fn) && parmno == 1)
360                 {
361                   tree in_charge;
362                   in_charge = in_charge_arg_for_name (DECL_NAME (clone));
363                   *pointer_map_insert (decl_map, parm) = in_charge;
364                 }
365               else if (DECL_ARTIFICIAL (parm)
366                        && DECL_NAME (parm) == vtt_parm_identifier)
367                 {
368                   /* For a subobject constructor or destructor, the next
369                      argument is the VTT parameter.  Remap the VTT_PARM
370                      from the CLONE to this parameter.  */
371                   if (DECL_HAS_VTT_PARM_P (clone))
372                     {
373                       DECL_ABSTRACT_ORIGIN (clone_parm) = parm;
374                       *pointer_map_insert (decl_map, parm) = clone_parm;
375                       clone_parm = TREE_CHAIN (clone_parm);
376                     }
377                   /* Otherwise, map the VTT parameter to `NULL'.  */
378                   else
379                     *pointer_map_insert (decl_map, parm)
380                        = fold_convert (TREE_TYPE (parm), null_pointer_node);
381                 }
382               /* Map other parameters to their equivalents in the cloned
383                  function.  */
384               else
385                 {
386                   *pointer_map_insert (decl_map, parm) = clone_parm;
387                   clone_parm = TREE_CHAIN (clone_parm);
388                 }
389             }
390 
391           if (targetm.cxx.cdtor_returns_this ())
392             {
393               parm = DECL_RESULT (fn);
394               clone_parm = DECL_RESULT (clone);
395               *pointer_map_insert (decl_map, parm) = clone_parm;
396             }
397 
398           /* Clone the body.  */
399           clone_body (clone, fn, decl_map);
400 
401           /* Clean up.  */
402           pointer_map_destroy (decl_map);
403         }
404 
405       /* The clone can throw iff the original function can throw.  */
406       cp_function_chain->can_throw = !TREE_NOTHROW (fn);
407 
408       /* Now, expand this function into RTL, if appropriate.  */
409       finish_function (0);
410       BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn);
411       if (alias)
412 	{
413 	  if (expand_or_defer_fn_1 (clone))
414 	    emit_associated_thunks (clone);
415 	}
416       else
417 	expand_or_defer_fn (clone);
418       first = false;
419     }
420   pop_from_top_level ();
421 
422   if (comdat_group)
423     {
424       DECL_COMDAT_GROUP (fns[1]) = comdat_group;
425       if (fns[2])
426 	{
427 	  struct cgraph_node *base_dtor_node, *deleting_dtor_node;
428 	  /* If *[CD][12]* dtors go into the *[CD]5* comdat group and dtor is
429 	     virtual, it goes into the same comdat group as well.  */
430 	  DECL_COMDAT_GROUP (fns[2]) = comdat_group;
431 	  base_dtor_node = cgraph_node (fns[0]);
432 	  deleting_dtor_node = cgraph_node (fns[2]);
433 	  gcc_assert (base_dtor_node->same_comdat_group == NULL);
434 	  gcc_assert (deleting_dtor_node->same_comdat_group == NULL);
435 	  base_dtor_node->same_comdat_group = deleting_dtor_node;
436 	  deleting_dtor_node->same_comdat_group = base_dtor_node;
437 	}
438     }
439 
440   /* We don't need to process the original function any further.  */
441   return 1;
442 }
443