]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/cp/optimize.c
re PR other/40784 (Revision 149725 caused autoconf warning in libstdc++)
[thirdparty/gcc.git] / gcc / cp / optimize.c
CommitLineData
46e8c075 1/* Perform optimizations on tree structure.
726a989a 2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2007, 2008
3c2426b9 3 Free Software Foundation, Inc.
46e8c075
MM
4 Written by Mark Michell (mark@codesourcery.com).
5
f5adbb8d 6This file is part of GCC.
46e8c075 7
f5adbb8d 8GCC is free software; you can redistribute it and/or modify it
06ceef4e 9under the terms of the GNU General Public License as published by
e77f031d 10the Free Software Foundation; either version 3, or (at your option)
06ceef4e
RK
11any later version.
12
f5adbb8d 13GCC is distributed in the hope that it will be useful, but
06ceef4e
RK
14WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16General Public License for more details.
9c96f3f8 17
06ceef4e 18You should have received a copy of the GNU General Public License
e77f031d
NC
19along with GCC; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. */
46e8c075
MM
21
22#include "config.h"
23#include "system.h"
4977bab6
ZW
24#include "coretypes.h"
25#include "tm.h"
46e8c075
MM
26#include "tree.h"
27#include "cp-tree.h"
28#include "rtl.h"
29#include "insn-config.h"
574a0ef5 30#include "input.h"
46e8c075 31#include "integrate.h"
9c96f3f8 32#include "toplev.h"
46e8c075 33#include "varray.h"
b850de4f 34#include "params.h"
11fe225a 35#include "hashtab.h"
44d10c10 36#include "target.h"
2b85879e 37#include "debug.h"
25af8512 38#include "tree-inline.h"
6de9cd9a
DN
39#include "flags.h"
40#include "langhooks.h"
41#include "diagnostic.h"
42#include "tree-dump.h"
726a989a 43#include "gimple.h"
46e8c075 44
46e8c075
MM
45/* Prototypes. */
46
b8ad8c93 47static void update_cloned_parm (tree, tree, bool);
95fabfd3 48
d60e5448
MM
49/* CLONED_PARM is a copy of CLONE, generated for a cloned constructor
50 or destructor. Update it to ensure that the source-position for
51 the cloned parameter matches that for the original, and that the
52 debugging generation code will be able to find the original PARM. */
53
54static void
b8ad8c93 55update_cloned_parm (tree parm, tree cloned_parm, bool first)
d60e5448
MM
56{
57 DECL_ABSTRACT_ORIGIN (cloned_parm) = parm;
d30a825a 58
c6002625 59 /* We may have taken its address. */
d30a825a
NS
60 TREE_ADDRESSABLE (cloned_parm) = TREE_ADDRESSABLE (parm);
61
c6002625 62 /* The definition might have different constness. */
d30a825a 63 TREE_READONLY (cloned_parm) = TREE_READONLY (parm);
c8094d83 64
b8ad8c93 65 TREE_USED (cloned_parm) = !first || TREE_USED (parm);
c8094d83 66
c6002625 67 /* The name may have changed from the declaration. */
d60e5448 68 DECL_NAME (cloned_parm) = DECL_NAME (parm);
f31686a3 69 DECL_SOURCE_LOCATION (cloned_parm) = DECL_SOURCE_LOCATION (parm);
e777303f 70 TREE_TYPE (cloned_parm) = TREE_TYPE (parm);
b3c4918f
AP
71
72 DECL_GIMPLE_REG_P (cloned_parm) = DECL_GIMPLE_REG_P (parm);
d60e5448
MM
73}
74
726a989a
RB
75
76/* FN is a function in High GIMPLE form that has a complete body and no
77 CFG. CLONE is a function whose body is to be set to a copy of FN,
78 mapping argument declarations according to the ARG_MAP splay_tree. */
9ff420f1
PB
79
80static void
81clone_body (tree clone, tree fn, void *arg_map)
82{
83 copy_body_data id;
726a989a
RB
84 gimple_seq new_body;
85
86 /* FN must already be in GIMPLE form. */
87 gcc_assert (gimple_body (fn));
9ff420f1 88
726a989a
RB
89 /* Clone the body, as if we were making an inline call. But, remap
90 the parameters in the callee to the parameters of caller. */
9ff420f1
PB
91 memset (&id, 0, sizeof (id));
92 id.src_fn = fn;
93 id.dst_fn = clone;
94 id.src_cfun = DECL_STRUCT_FUNCTION (fn);
726a989a 95 id.decl_map = (struct pointer_map_t *) arg_map;
9ff420f1
PB
96
97 id.copy_decl = copy_decl_no_change;
98 id.transform_call_graph_edges = CB_CGE_DUPLICATE;
99 id.transform_new_cfg = true;
100 id.transform_return_to_modify = false;
726a989a 101 id.transform_lang_insert_block = NULL;
9ff420f1
PB
102
103 /* We're not inside any EH region. */
104 id.eh_region = -1;
105
106 /* Actually copy the body. */
726a989a
RB
107 new_body = remap_gimple_seq (gimple_body (fn), &id);
108 gimple_set_body (clone, new_body);
9ff420f1
PB
109}
110
db9b2174 111/* FN is a function that has a complete body. Clone the body as
838dfd8a 112 necessary. Returns nonzero if there's no longer any need to
db9b2174
MM
113 process the main body. */
114
4977bab6
ZW
115bool
116maybe_clone_body (tree fn)
db9b2174 117{
db9b2174 118 tree clone;
b8ad8c93 119 bool first = true;
db9b2174 120
db9b2174
MM
121 /* We only clone constructors and destructors. */
122 if (!DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn)
123 && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn))
124 return 0;
125
5daf7c0a 126 /* Emit the DWARF1 abstract instance. */
2b85879e 127 (*debug_hooks->deferred_inline_function) (fn);
5daf7c0a 128
db9b2174
MM
129 /* We know that any clones immediately follow FN in the TYPE_METHODS
130 list. */
f44b0c8e 131 push_to_top_level ();
4684cd27 132 FOR_EACH_CLONE (clone, fn)
db9b2174
MM
133 {
134 tree parm;
135 tree clone_parm;
136 int parmno;
6be42dd4 137 struct pointer_map_t *decl_map;
db9b2174
MM
138
139 /* Update CLONE's source position information to match FN's. */
f31686a3 140 DECL_SOURCE_LOCATION (clone) = DECL_SOURCE_LOCATION (fn);
79065db2 141 DECL_DECLARED_INLINE_P (clone) = DECL_DECLARED_INLINE_P (fn);
3ec6bad3
MM
142 DECL_COMDAT (clone) = DECL_COMDAT (fn);
143 DECL_WEAK (clone) = DECL_WEAK (fn);
fc26fae3
RAE
144
145 /* We don't copy the comdat group from fn to clone because the assembler
146 name of fn was corrupted by write_mangled_name by adding *INTERNAL*
147 to it. By doing so, it also corrupted the comdat group. */
148 if (DECL_ONE_ONLY (fn))
149 DECL_COMDAT_GROUP (clone) = cxx_comdat_group (clone);
3ec6bad3 150 DECL_SECTION_NAME (clone) = DECL_SECTION_NAME (fn);
459c43ad
MM
151 DECL_USE_TEMPLATE (clone) = DECL_USE_TEMPLATE (fn);
152 DECL_EXTERNAL (clone) = DECL_EXTERNAL (fn);
153 DECL_INTERFACE_KNOWN (clone) = DECL_INTERFACE_KNOWN (fn);
154 DECL_NOT_REALLY_EXTERN (clone) = DECL_NOT_REALLY_EXTERN (fn);
b96ada87 155 TREE_PUBLIC (clone) = TREE_PUBLIC (fn);
968b41a1 156 DECL_VISIBILITY (clone) = DECL_VISIBILITY (fn);
d7afec4b 157 DECL_VISIBILITY_SPECIFIED (clone) = DECL_VISIBILITY_SPECIFIED (fn);
39e6670f 158 DECL_DLLIMPORT_P (clone) = DECL_DLLIMPORT_P (fn);
db9b2174 159
c6002625 160 /* Adjust the parameter names and locations. */
02a1a68c
NS
161 parm = DECL_ARGUMENTS (fn);
162 clone_parm = DECL_ARGUMENTS (clone);
4a90862e 163 /* Update the `this' parameter, which is always first. */
b8ad8c93 164 update_cloned_parm (parm, clone_parm, first);
4a90862e
JM
165 parm = TREE_CHAIN (parm);
166 clone_parm = TREE_CHAIN (clone_parm);
02a1a68c
NS
167 if (DECL_HAS_IN_CHARGE_PARM_P (fn))
168 parm = TREE_CHAIN (parm);
169 if (DECL_HAS_VTT_PARM_P (fn))
170 parm = TREE_CHAIN (parm);
171 if (DECL_HAS_VTT_PARM_P (clone))
172 clone_parm = TREE_CHAIN (clone_parm);
173 for (; parm;
174 parm = TREE_CHAIN (parm), clone_parm = TREE_CHAIN (clone_parm))
85b22f78 175 /* Update this parameter. */
b8ad8c93 176 update_cloned_parm (parm, clone_parm, first);
02a1a68c 177
db9b2174 178 /* Start processing the function. */
058b15c1 179 start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED);
db9b2174 180
db9b2174 181 /* Remap the parameters. */
6be42dd4 182 decl_map = pointer_map_create ();
db9b2174
MM
183 for (parmno = 0,
184 parm = DECL_ARGUMENTS (fn),
185 clone_parm = DECL_ARGUMENTS (clone);
186 parm;
187 ++parmno,
188 parm = TREE_CHAIN (parm))
189 {
190 /* Map the in-charge parameter to an appropriate constant. */
191 if (DECL_HAS_IN_CHARGE_PARM_P (fn) && parmno == 1)
192 {
193 tree in_charge;
298d6f60 194 in_charge = in_charge_arg_for_name (DECL_NAME (clone));
6be42dd4 195 *pointer_map_insert (decl_map, parm) = in_charge;
e0fff4b3
JM
196 }
197 else if (DECL_ARTIFICIAL (parm)
198 && DECL_NAME (parm) == vtt_parm_identifier)
199 {
3ec6bad3
MM
200 /* For a subobject constructor or destructor, the next
201 argument is the VTT parameter. Remap the VTT_PARM
202 from the CLONE to this parameter. */
e0fff4b3 203 if (DECL_HAS_VTT_PARM_P (clone))
3ec6bad3 204 {
5daf7c0a 205 DECL_ABSTRACT_ORIGIN (clone_parm) = parm;
6be42dd4 206 *pointer_map_insert (decl_map, parm) = clone_parm;
3ec6bad3
MM
207 clone_parm = TREE_CHAIN (clone_parm);
208 }
209 /* Otherwise, map the VTT parameter to `NULL'. */
e0fff4b3 210 else
6be42dd4 211 *pointer_map_insert (decl_map, parm) = null_pointer_node;
db9b2174
MM
212 }
213 /* Map other parameters to their equivalents in the cloned
214 function. */
215 else
216 {
6be42dd4 217 *pointer_map_insert (decl_map, parm) = clone_parm;
db9b2174
MM
218 clone_parm = TREE_CHAIN (clone_parm);
219 }
220 }
221
44d10c10
PB
222 if (targetm.cxx.cdtor_returns_this ())
223 {
224 parm = DECL_RESULT (fn);
225 clone_parm = DECL_RESULT (clone);
6be42dd4 226 *pointer_map_insert (decl_map, parm) = clone_parm;
44d10c10 227 }
25af8512
AO
228 /* Clone the body. */
229 clone_body (clone, fn, decl_map);
db9b2174
MM
230
231 /* Clean up. */
6be42dd4 232 pointer_map_destroy (decl_map);
db9b2174 233
b2dd096b
MM
234 /* The clone can throw iff the original function can throw. */
235 cp_function_chain->can_throw = !TREE_NOTHROW (fn);
236
db9b2174 237 /* Now, expand this function into RTL, if appropriate. */
5daf7c0a
JM
238 finish_function (0);
239 BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn);
726a989a 240 DECL_SAVED_TREE (clone) = NULL;
8cd2462c 241 expand_or_defer_fn (clone);
b8ad8c93 242 first = false;
db9b2174 243 }
f44b0c8e 244 pop_from_top_level ();
9c96f3f8 245
db9b2174
MM
246 /* We don't need to process the original function any further. */
247 return 1;
248}