1 /* Perform optimizations on tree structure.
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004
3 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 2, 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 COPYING. If not, write to the Free
20 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 #include "coretypes.h"
30 #include "insn-config.h"
32 #include "integrate.h"
38 #include "tree-inline.h"
42 static tree
calls_setjmp_r (tree
*, int *, void *);
43 static void update_cloned_parm (tree
, tree
);
45 /* Called from calls_setjmp_p via walk_tree. */
48 calls_setjmp_r (tree
*tp
, int *walk_subtrees ATTRIBUTE_UNUSED
,
49 void *data ATTRIBUTE_UNUSED
)
51 /* We're only interested in FUNCTION_DECLS. */
52 if (TREE_CODE (*tp
) != FUNCTION_DECL
)
55 return setjmp_call_p (*tp
) ? *tp
: NULL_TREE
;
58 /* Returns nonzero if FN calls `setjmp' or some other function that
59 can return more than once. This function is conservative; it may
60 occasionally return a nonzero value even when FN does not actually
64 calls_setjmp_p (tree fn
)
66 return walk_tree_without_duplicates (&DECL_SAVED_TREE (fn
),
71 /* CLONED_PARM is a copy of CLONE, generated for a cloned constructor
72 or destructor. Update it to ensure that the source-position for
73 the cloned parameter matches that for the original, and that the
74 debugging generation code will be able to find the original PARM. */
77 update_cloned_parm (tree parm
, tree cloned_parm
)
79 DECL_ABSTRACT_ORIGIN (cloned_parm
) = parm
;
81 /* We may have taken its address. */
82 TREE_ADDRESSABLE (cloned_parm
) = TREE_ADDRESSABLE (parm
);
84 /* The definition might have different constness. */
85 TREE_READONLY (cloned_parm
) = TREE_READONLY (parm
);
87 TREE_USED (cloned_parm
) = TREE_USED (parm
);
89 /* The name may have changed from the declaration. */
90 DECL_NAME (cloned_parm
) = DECL_NAME (parm
);
91 DECL_SOURCE_LOCATION (cloned_parm
) = DECL_SOURCE_LOCATION (parm
);
94 /* FN is a function that has a complete body. Clone the body as
95 necessary. Returns nonzero if there's no longer any need to
96 process the main body. */
99 maybe_clone_body (tree fn
)
103 /* We only clone constructors and destructors. */
104 if (!DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn
)
105 && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn
))
108 /* Emit the DWARF1 abstract instance. */
109 (*debug_hooks
->deferred_inline_function
) (fn
);
111 /* We know that any clones immediately follow FN in the TYPE_METHODS
113 for (clone
= TREE_CHAIN (fn
);
114 clone
&& DECL_CLONED_FUNCTION_P (clone
);
115 clone
= TREE_CHAIN (clone
))
122 /* Update CLONE's source position information to match FN's. */
123 DECL_SOURCE_LOCATION (clone
) = DECL_SOURCE_LOCATION (fn
);
124 DECL_INLINE (clone
) = DECL_INLINE (fn
);
125 DECL_DECLARED_INLINE_P (clone
) = DECL_DECLARED_INLINE_P (fn
);
126 DECL_COMDAT (clone
) = DECL_COMDAT (fn
);
127 DECL_WEAK (clone
) = DECL_WEAK (fn
);
128 DECL_ONE_ONLY (clone
) = DECL_ONE_ONLY (fn
);
129 DECL_SECTION_NAME (clone
) = DECL_SECTION_NAME (fn
);
130 DECL_USE_TEMPLATE (clone
) = DECL_USE_TEMPLATE (fn
);
131 DECL_EXTERNAL (clone
) = DECL_EXTERNAL (fn
);
132 DECL_INTERFACE_KNOWN (clone
) = DECL_INTERFACE_KNOWN (fn
);
133 DECL_NOT_REALLY_EXTERN (clone
) = DECL_NOT_REALLY_EXTERN (fn
);
134 TREE_PUBLIC (clone
) = TREE_PUBLIC (fn
);
135 DECL_VISIBILITY (clone
) = DECL_VISIBILITY (fn
);
137 /* Adjust the parameter names and locations. */
138 parm
= DECL_ARGUMENTS (fn
);
139 clone_parm
= DECL_ARGUMENTS (clone
);
140 /* Update the `this' parameter, which is always first. */
141 update_cloned_parm (parm
, clone_parm
);
142 parm
= TREE_CHAIN (parm
);
143 clone_parm
= TREE_CHAIN (clone_parm
);
144 if (DECL_HAS_IN_CHARGE_PARM_P (fn
))
145 parm
= TREE_CHAIN (parm
);
146 if (DECL_HAS_VTT_PARM_P (fn
))
147 parm
= TREE_CHAIN (parm
);
148 if (DECL_HAS_VTT_PARM_P (clone
))
149 clone_parm
= TREE_CHAIN (clone_parm
);
151 parm
= TREE_CHAIN (parm
), clone_parm
= TREE_CHAIN (clone_parm
))
152 /* Update this parameter. */
153 update_cloned_parm (parm
, clone_parm
);
155 /* Start processing the function. */
156 push_to_top_level ();
157 start_function (NULL_TREE
, clone
, NULL_TREE
, SF_PRE_PARSED
);
159 /* Remap the parameters. */
160 decl_map
= splay_tree_new (splay_tree_compare_pointers
, NULL
, NULL
);
162 parm
= DECL_ARGUMENTS (fn
),
163 clone_parm
= DECL_ARGUMENTS (clone
);
166 parm
= TREE_CHAIN (parm
))
168 /* Map the in-charge parameter to an appropriate constant. */
169 if (DECL_HAS_IN_CHARGE_PARM_P (fn
) && parmno
== 1)
172 in_charge
= in_charge_arg_for_name (DECL_NAME (clone
));
173 splay_tree_insert (decl_map
,
174 (splay_tree_key
) parm
,
175 (splay_tree_value
) in_charge
);
177 else if (DECL_ARTIFICIAL (parm
)
178 && DECL_NAME (parm
) == vtt_parm_identifier
)
180 /* For a subobject constructor or destructor, the next
181 argument is the VTT parameter. Remap the VTT_PARM
182 from the CLONE to this parameter. */
183 if (DECL_HAS_VTT_PARM_P (clone
))
185 DECL_ABSTRACT_ORIGIN (clone_parm
) = parm
;
186 splay_tree_insert (decl_map
,
187 (splay_tree_key
) parm
,
188 (splay_tree_value
) clone_parm
);
189 clone_parm
= TREE_CHAIN (clone_parm
);
191 /* Otherwise, map the VTT parameter to `NULL'. */
194 splay_tree_insert (decl_map
,
195 (splay_tree_key
) parm
,
196 (splay_tree_value
) null_pointer_node
);
199 /* Map other parameters to their equivalents in the cloned
203 splay_tree_insert (decl_map
,
204 (splay_tree_key
) parm
,
205 (splay_tree_value
) clone_parm
);
206 clone_parm
= TREE_CHAIN (clone_parm
);
210 /* Clone the body. */
211 clone_body (clone
, fn
, decl_map
);
214 splay_tree_delete (decl_map
);
216 /* The clone can throw iff the original function can throw. */
217 cp_function_chain
->can_throw
= !TREE_NOTHROW (fn
);
219 /* Now, expand this function into RTL, if appropriate. */
221 BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone
)) = DECL_INITIAL (fn
);
222 expand_or_defer_fn (clone
);
223 pop_from_top_level ();
226 /* We don't need to process the original function any further. */