]>
Commit | Line | Data |
---|---|---|
46e8c075 | 1 | /* Perform optimizations on tree structure. |
e77f031d | 2 | Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2007 |
3c2426b9 | 3 | Free Software Foundation, Inc. |
46e8c075 MM |
4 | Written by Mark Michell (mark@codesourcery.com). |
5 | ||
f5adbb8d | 6 | This file is part of GCC. |
46e8c075 | 7 | |
f5adbb8d | 8 | GCC is free software; you can redistribute it and/or modify it |
06ceef4e | 9 | under the terms of the GNU General Public License as published by |
e77f031d | 10 | the Free Software Foundation; either version 3, or (at your option) |
06ceef4e RK |
11 | any later version. |
12 | ||
f5adbb8d | 13 | GCC is distributed in the hope that it will be useful, but |
06ceef4e RK |
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. | |
9c96f3f8 | 17 | |
06ceef4e | 18 | You should have received a copy of the GNU General Public License |
e77f031d NC |
19 | along 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" | |
eadf906f | 43 | #include "tree-gimple.h" |
46e8c075 | 44 | |
46e8c075 MM |
45 | /* Prototypes. */ |
46 | ||
b8ad8c93 | 47 | static 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 | ||
54 | static void | |
b8ad8c93 | 55 | update_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 | ||
9ff420f1 PB |
75 | /* FN is a function that has a complete body, and CLONE is a function whose |
76 | body is to be set to a copy of FN, mapping argument declarations according | |
77 | to the ARG_MAP splay_tree. */ | |
78 | ||
79 | static void | |
80 | clone_body (tree clone, tree fn, void *arg_map) | |
81 | { | |
82 | copy_body_data id; | |
83 | ||
84 | /* Clone the body, as if we were making an inline call. But, remap the | |
85 | parameters in the callee to the parameters of caller. */ | |
86 | memset (&id, 0, sizeof (id)); | |
87 | id.src_fn = fn; | |
88 | id.dst_fn = clone; | |
89 | id.src_cfun = DECL_STRUCT_FUNCTION (fn); | |
90 | id.decl_map = (struct pointer_map_t *)arg_map; | |
91 | ||
92 | id.copy_decl = copy_decl_no_change; | |
93 | id.transform_call_graph_edges = CB_CGE_DUPLICATE; | |
94 | id.transform_new_cfg = true; | |
95 | id.transform_return_to_modify = false; | |
96 | id.transform_lang_insert_block = insert_block; | |
97 | ||
98 | /* We're not inside any EH region. */ | |
99 | id.eh_region = -1; | |
100 | ||
101 | /* Actually copy the body. */ | |
102 | append_to_statement_list_force (copy_generic_body (&id), | |
103 | &DECL_SAVED_TREE (clone)); | |
104 | } | |
105 | ||
db9b2174 | 106 | /* FN is a function that has a complete body. Clone the body as |
838dfd8a | 107 | necessary. Returns nonzero if there's no longer any need to |
db9b2174 MM |
108 | process the main body. */ |
109 | ||
4977bab6 ZW |
110 | bool |
111 | maybe_clone_body (tree fn) | |
db9b2174 | 112 | { |
db9b2174 | 113 | tree clone; |
b8ad8c93 | 114 | bool first = true; |
db9b2174 | 115 | |
db9b2174 MM |
116 | /* We only clone constructors and destructors. */ |
117 | if (!DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn) | |
118 | && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn)) | |
119 | return 0; | |
120 | ||
5daf7c0a | 121 | /* Emit the DWARF1 abstract instance. */ |
2b85879e | 122 | (*debug_hooks->deferred_inline_function) (fn); |
5daf7c0a | 123 | |
db9b2174 MM |
124 | /* We know that any clones immediately follow FN in the TYPE_METHODS |
125 | list. */ | |
f44b0c8e | 126 | push_to_top_level (); |
4684cd27 | 127 | FOR_EACH_CLONE (clone, fn) |
db9b2174 MM |
128 | { |
129 | tree parm; | |
130 | tree clone_parm; | |
131 | int parmno; | |
6be42dd4 | 132 | struct pointer_map_t *decl_map; |
db9b2174 MM |
133 | |
134 | /* Update CLONE's source position information to match FN's. */ | |
f31686a3 | 135 | DECL_SOURCE_LOCATION (clone) = DECL_SOURCE_LOCATION (fn); |
99389463 | 136 | DECL_INLINE (clone) = DECL_INLINE (fn); |
79065db2 | 137 | DECL_DECLARED_INLINE_P (clone) = DECL_DECLARED_INLINE_P (fn); |
3ec6bad3 MM |
138 | DECL_COMDAT (clone) = DECL_COMDAT (fn); |
139 | DECL_WEAK (clone) = DECL_WEAK (fn); | |
140 | DECL_ONE_ONLY (clone) = DECL_ONE_ONLY (fn); | |
141 | DECL_SECTION_NAME (clone) = DECL_SECTION_NAME (fn); | |
459c43ad MM |
142 | DECL_USE_TEMPLATE (clone) = DECL_USE_TEMPLATE (fn); |
143 | DECL_EXTERNAL (clone) = DECL_EXTERNAL (fn); | |
144 | DECL_INTERFACE_KNOWN (clone) = DECL_INTERFACE_KNOWN (fn); | |
145 | DECL_NOT_REALLY_EXTERN (clone) = DECL_NOT_REALLY_EXTERN (fn); | |
b96ada87 | 146 | TREE_PUBLIC (clone) = TREE_PUBLIC (fn); |
968b41a1 | 147 | DECL_VISIBILITY (clone) = DECL_VISIBILITY (fn); |
d7afec4b | 148 | DECL_VISIBILITY_SPECIFIED (clone) = DECL_VISIBILITY_SPECIFIED (fn); |
39e6670f | 149 | DECL_DLLIMPORT_P (clone) = DECL_DLLIMPORT_P (fn); |
db9b2174 | 150 | |
c6002625 | 151 | /* Adjust the parameter names and locations. */ |
02a1a68c NS |
152 | parm = DECL_ARGUMENTS (fn); |
153 | clone_parm = DECL_ARGUMENTS (clone); | |
4a90862e | 154 | /* Update the `this' parameter, which is always first. */ |
b8ad8c93 | 155 | update_cloned_parm (parm, clone_parm, first); |
4a90862e JM |
156 | parm = TREE_CHAIN (parm); |
157 | clone_parm = TREE_CHAIN (clone_parm); | |
02a1a68c NS |
158 | if (DECL_HAS_IN_CHARGE_PARM_P (fn)) |
159 | parm = TREE_CHAIN (parm); | |
160 | if (DECL_HAS_VTT_PARM_P (fn)) | |
161 | parm = TREE_CHAIN (parm); | |
162 | if (DECL_HAS_VTT_PARM_P (clone)) | |
163 | clone_parm = TREE_CHAIN (clone_parm); | |
164 | for (; parm; | |
165 | parm = TREE_CHAIN (parm), clone_parm = TREE_CHAIN (clone_parm)) | |
85b22f78 | 166 | /* Update this parameter. */ |
b8ad8c93 | 167 | update_cloned_parm (parm, clone_parm, first); |
02a1a68c | 168 | |
db9b2174 | 169 | /* Start processing the function. */ |
058b15c1 | 170 | start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED); |
db9b2174 | 171 | |
db9b2174 | 172 | /* Remap the parameters. */ |
6be42dd4 | 173 | decl_map = pointer_map_create (); |
db9b2174 MM |
174 | for (parmno = 0, |
175 | parm = DECL_ARGUMENTS (fn), | |
176 | clone_parm = DECL_ARGUMENTS (clone); | |
177 | parm; | |
178 | ++parmno, | |
179 | parm = TREE_CHAIN (parm)) | |
180 | { | |
181 | /* Map the in-charge parameter to an appropriate constant. */ | |
182 | if (DECL_HAS_IN_CHARGE_PARM_P (fn) && parmno == 1) | |
183 | { | |
184 | tree in_charge; | |
298d6f60 | 185 | in_charge = in_charge_arg_for_name (DECL_NAME (clone)); |
6be42dd4 | 186 | *pointer_map_insert (decl_map, parm) = in_charge; |
e0fff4b3 JM |
187 | } |
188 | else if (DECL_ARTIFICIAL (parm) | |
189 | && DECL_NAME (parm) == vtt_parm_identifier) | |
190 | { | |
3ec6bad3 MM |
191 | /* For a subobject constructor or destructor, the next |
192 | argument is the VTT parameter. Remap the VTT_PARM | |
193 | from the CLONE to this parameter. */ | |
e0fff4b3 | 194 | if (DECL_HAS_VTT_PARM_P (clone)) |
3ec6bad3 | 195 | { |
5daf7c0a | 196 | DECL_ABSTRACT_ORIGIN (clone_parm) = parm; |
6be42dd4 | 197 | *pointer_map_insert (decl_map, parm) = clone_parm; |
3ec6bad3 MM |
198 | clone_parm = TREE_CHAIN (clone_parm); |
199 | } | |
200 | /* Otherwise, map the VTT parameter to `NULL'. */ | |
e0fff4b3 | 201 | else |
6be42dd4 | 202 | *pointer_map_insert (decl_map, parm) = null_pointer_node; |
db9b2174 MM |
203 | } |
204 | /* Map other parameters to their equivalents in the cloned | |
205 | function. */ | |
206 | else | |
207 | { | |
6be42dd4 | 208 | *pointer_map_insert (decl_map, parm) = clone_parm; |
db9b2174 MM |
209 | clone_parm = TREE_CHAIN (clone_parm); |
210 | } | |
211 | } | |
212 | ||
44d10c10 PB |
213 | if (targetm.cxx.cdtor_returns_this ()) |
214 | { | |
215 | parm = DECL_RESULT (fn); | |
216 | clone_parm = DECL_RESULT (clone); | |
6be42dd4 | 217 | *pointer_map_insert (decl_map, parm) = clone_parm; |
44d10c10 | 218 | } |
25af8512 AO |
219 | /* Clone the body. */ |
220 | clone_body (clone, fn, decl_map); | |
db9b2174 MM |
221 | |
222 | /* Clean up. */ | |
6be42dd4 | 223 | pointer_map_destroy (decl_map); |
db9b2174 | 224 | |
b2dd096b MM |
225 | /* The clone can throw iff the original function can throw. */ |
226 | cp_function_chain->can_throw = !TREE_NOTHROW (fn); | |
227 | ||
db9b2174 | 228 | /* Now, expand this function into RTL, if appropriate. */ |
5daf7c0a JM |
229 | finish_function (0); |
230 | BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn); | |
8cd2462c | 231 | expand_or_defer_fn (clone); |
b8ad8c93 | 232 | first = false; |
db9b2174 | 233 | } |
f44b0c8e | 234 | pop_from_top_level (); |
9c96f3f8 | 235 | |
db9b2174 MM |
236 | /* We don't need to process the original function any further. */ |
237 | return 1; | |
238 | } |