]>
Commit | Line | Data |
---|---|---|
588d3ade | 1 | /* Control and data flow functions for trees. |
d9221e01 | 2 | Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc. |
588d3ade AO |
3 | Contributed by Alexandre Oliva <aoliva@redhat.com> |
4 | ||
54a7b573 | 5 | This file is part of GCC. |
588d3ade | 6 | |
54a7b573 | 7 | GCC is free software; you can redistribute it and/or modify |
588d3ade AO |
8 | it under the terms of the GNU General Public License as published by |
9 | the Free Software Foundation; either version 2, or (at your option) | |
10 | any later version. | |
11 | ||
54a7b573 | 12 | GCC is distributed in the hope that it will be useful, |
588d3ade AO |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
54a7b573 | 18 | along with GCC; see the file COPYING. If not, write to |
588d3ade AO |
19 | the Free Software Foundation, 59 Temple Place - Suite 330, |
20 | Boston, MA 02111-1307, USA. */ | |
21 | ||
22 | #include "config.h" | |
23 | #include "system.h" | |
4977bab6 ZW |
24 | #include "coretypes.h" |
25 | #include "tm.h" | |
69dcadff | 26 | #include "toplev.h" |
588d3ade AO |
27 | #include "tree.h" |
28 | #include "tree-inline.h" | |
d4e4baa9 AO |
29 | #include "rtl.h" |
30 | #include "expr.h" | |
31 | #include "flags.h" | |
32 | #include "params.h" | |
33 | #include "input.h" | |
34 | #include "insn-config.h" | |
35 | #include "integrate.h" | |
36 | #include "varray.h" | |
37 | #include "hashtab.h" | |
38 | #include "splay-tree.h" | |
d23c55c2 | 39 | #include "langhooks.h" |
1c4a429a | 40 | #include "cgraph.h" |
ddd2d57e | 41 | #include "intl.h" |
c5b6f18e | 42 | #include "diagnostic.h" |
d4e4baa9 AO |
43 | |
44 | /* This should be eventually be generalized to other languages, but | |
45 | this would require a shared function-as-trees infrastructure. */ | |
d436bff8 | 46 | #ifndef INLINER_FOR_JAVA |
d92b4486 | 47 | #include "c-common.h" |
d436bff8 AH |
48 | #else /* INLINER_FOR_JAVA */ |
49 | #include "parse.h" | |
50 | #include "java-tree.h" | |
51 | #endif /* INLINER_FOR_JAVA */ | |
588d3ade | 52 | |
588d3ade | 53 | /* 0 if we should not perform inlining. |
d92b4486 KH |
54 | 1 if we should expand functions calls inline at the tree level. |
55 | 2 if we should consider *all* functions to be inline | |
588d3ade AO |
56 | candidates. */ |
57 | ||
58 | int flag_inline_trees = 0; | |
d4e4baa9 AO |
59 | |
60 | /* To Do: | |
61 | ||
62 | o In order to make inlining-on-trees work, we pessimized | |
63 | function-local static constants. In particular, they are now | |
64 | always output, even when not addressed. Fix this by treating | |
65 | function-local static constants just like global static | |
66 | constants; the back-end already knows not to output them if they | |
67 | are not needed. | |
68 | ||
69 | o Provide heuristics to clamp inlining of recursive template | |
70 | calls? */ | |
71 | ||
72 | /* Data required for function inlining. */ | |
73 | ||
74 | typedef struct inline_data | |
75 | { | |
76 | /* A stack of the functions we are inlining. For example, if we are | |
77 | compiling `f', which calls `g', which calls `h', and we are | |
78 | inlining the body of `h', the stack will contain, `h', followed | |
79 | by `g', followed by `f'. The first few elements of the stack may | |
80 | contain other functions that we know we should not recurse into, | |
81 | even though they are not directly being inlined. */ | |
82 | varray_type fns; | |
83 | /* The index of the first element of FNS that really represents an | |
84 | inlined function. */ | |
85 | unsigned first_inlined_fn; | |
86 | /* The label to jump to when a return statement is encountered. If | |
87 | this value is NULL, then return statements will simply be | |
88 | remapped as return statements, rather than as jumps. */ | |
89 | tree ret_label; | |
90 | /* The map from local declarations in the inlined function to | |
91 | equivalents in the function into which it is being inlined. */ | |
92 | splay_tree decl_map; | |
93 | /* Nonzero if we are currently within the cleanup for a | |
94 | TARGET_EXPR. */ | |
95 | int in_target_cleanup_p; | |
d4e4baa9 AO |
96 | /* A list of the functions current function has inlined. */ |
97 | varray_type inlined_fns; | |
d4e4baa9 AO |
98 | /* We use the same mechanism to build clones that we do to perform |
99 | inlining. However, there are a few places where we need to | |
100 | distinguish between those two situations. This flag is true if | |
101 | we are cloning, rather than inlining. */ | |
102 | bool cloning_p; | |
103 | /* Hash table used to prevent walk_tree from visiting the same node | |
104 | umpteen million times. */ | |
105 | htab_t tree_pruner; | |
e72fcfe8 JH |
106 | /* Decl of function we are inlining into. */ |
107 | tree decl; | |
b58b1157 | 108 | tree current_decl; |
d4e4baa9 AO |
109 | } inline_data; |
110 | ||
111 | /* Prototypes. */ | |
112 | ||
46c5ad27 AJ |
113 | static tree declare_return_variable (inline_data *, tree, tree *); |
114 | static tree copy_body_r (tree *, int *, void *); | |
115 | static tree copy_body (inline_data *); | |
116 | static tree expand_call_inline (tree *, int *, void *); | |
117 | static void expand_calls_inline (tree *, inline_data *); | |
b3c3af2f | 118 | static bool inlinable_function_p (tree); |
46c5ad27 | 119 | static tree remap_decl (tree, inline_data *); |
3c2a7a6a | 120 | static tree remap_type (tree, inline_data *); |
d436bff8 | 121 | #ifndef INLINER_FOR_JAVA |
46c5ad27 AJ |
122 | static tree initialize_inlined_parameters (inline_data *, tree, tree); |
123 | static void remap_block (tree, tree, inline_data *); | |
124 | static void copy_scope_stmt (tree *, int *, inline_data *); | |
d436bff8 | 125 | #else /* INLINER_FOR_JAVA */ |
46c5ad27 AJ |
126 | static tree initialize_inlined_parameters (inline_data *, tree, tree, tree); |
127 | static void remap_block (tree *, tree, inline_data *); | |
128 | static tree add_stmt_to_compound (tree, tree, tree); | |
50aadcbc | 129 | #endif /* INLINER_FOR_JAVA */ |
d4e4baa9 | 130 | |
5e20bdd7 JZ |
131 | /* Insert a tree->tree mapping for ID. Despite the name suggests |
132 | that the trees should be variables, it is used for more than that. */ | |
133 | ||
134 | static void | |
135 | insert_decl_map (inline_data *id, tree key, tree value) | |
136 | { | |
137 | splay_tree_insert (id->decl_map, (splay_tree_key) key, | |
138 | (splay_tree_value) value); | |
139 | ||
140 | /* Always insert an identity map as well. If we see this same new | |
141 | node again, we won't want to duplicate it a second time. */ | |
142 | if (key != value) | |
143 | splay_tree_insert (id->decl_map, (splay_tree_key) value, | |
144 | (splay_tree_value) value); | |
145 | } | |
146 | ||
d4e4baa9 AO |
147 | /* Remap DECL during the copying of the BLOCK tree for the function. */ |
148 | ||
149 | static tree | |
46c5ad27 | 150 | remap_decl (tree decl, inline_data *id) |
d4e4baa9 AO |
151 | { |
152 | splay_tree_node n; | |
153 | tree fn; | |
154 | ||
155 | /* We only remap local variables in the current function. */ | |
156 | fn = VARRAY_TOP_TREE (id->fns); | |
69dcadff | 157 | if (! (*lang_hooks.tree_inlining.auto_var_in_fn_p) (decl, fn)) |
d4e4baa9 AO |
158 | return NULL_TREE; |
159 | ||
160 | /* See if we have remapped this declaration. */ | |
161 | n = splay_tree_lookup (id->decl_map, (splay_tree_key) decl); | |
3c2a7a6a | 162 | |
d4e4baa9 AO |
163 | /* If we didn't already have an equivalent for this declaration, |
164 | create one now. */ | |
165 | if (!n) | |
166 | { | |
167 | tree t; | |
168 | ||
169 | /* Make a copy of the variable or label. */ | |
3c2a7a6a RH |
170 | t = copy_decl_for_inlining (decl, fn, VARRAY_TREE (id->fns, 0)); |
171 | ||
172 | /* Remap types, if necessary. */ | |
173 | TREE_TYPE (t) = remap_type (TREE_TYPE (t), id); | |
174 | if (TREE_CODE (t) == TYPE_DECL) | |
175 | DECL_ORIGINAL_TYPE (t) = remap_type (DECL_ORIGINAL_TYPE (t), id); | |
176 | else if (TREE_CODE (t) == PARM_DECL) | |
177 | DECL_ARG_TYPE_AS_WRITTEN (t) | |
178 | = remap_type (DECL_ARG_TYPE_AS_WRITTEN (t), id); | |
179 | ||
180 | /* Remap sizes as necessary. */ | |
181 | walk_tree (&DECL_SIZE (t), copy_body_r, id, NULL); | |
182 | walk_tree (&DECL_SIZE_UNIT (t), copy_body_r, id, NULL); | |
d4e4baa9 | 183 | |
d436bff8 | 184 | #ifndef INLINER_FOR_JAVA |
d4e4baa9 | 185 | if (! DECL_NAME (t) && TREE_TYPE (t) |
69dcadff | 186 | && (*lang_hooks.tree_inlining.anon_aggr_type_p) (TREE_TYPE (t))) |
d4e4baa9 AO |
187 | { |
188 | /* For a VAR_DECL of anonymous type, we must also copy the | |
3c2a7a6a | 189 | member VAR_DECLS here and rechain the DECL_ANON_UNION_ELEMS. */ |
d4e4baa9 AO |
190 | tree members = NULL; |
191 | tree src; | |
d92b4486 | 192 | |
d4e4baa9 AO |
193 | for (src = DECL_ANON_UNION_ELEMS (t); src; |
194 | src = TREE_CHAIN (src)) | |
195 | { | |
196 | tree member = remap_decl (TREE_VALUE (src), id); | |
197 | ||
198 | if (TREE_PURPOSE (src)) | |
199 | abort (); | |
200 | members = tree_cons (NULL, member, members); | |
201 | } | |
202 | DECL_ANON_UNION_ELEMS (t) = nreverse (members); | |
203 | } | |
d436bff8 | 204 | #endif /* not INLINER_FOR_JAVA */ |
d92b4486 | 205 | |
d4e4baa9 AO |
206 | /* Remember it, so that if we encounter this local entity |
207 | again we can reuse this copy. */ | |
5e20bdd7 JZ |
208 | insert_decl_map (id, decl, t); |
209 | return t; | |
d4e4baa9 AO |
210 | } |
211 | ||
212 | return (tree) n->value; | |
213 | } | |
214 | ||
3c2a7a6a RH |
215 | static tree |
216 | remap_type (tree type, inline_data *id) | |
217 | { | |
218 | splay_tree_node node; | |
219 | tree new, t; | |
220 | ||
221 | if (type == NULL) | |
222 | return type; | |
223 | ||
224 | /* See if we have remapped this type. */ | |
225 | node = splay_tree_lookup (id->decl_map, (splay_tree_key) type); | |
226 | if (node) | |
227 | return (tree) node->value; | |
228 | ||
229 | /* The type only needs remapping if it's variably modified. */ | |
230 | if (! variably_modified_type_p (type)) | |
231 | { | |
5e20bdd7 | 232 | insert_decl_map (id, type, type); |
3c2a7a6a RH |
233 | return type; |
234 | } | |
235 | ||
236 | /* We do need a copy. build and register it now. */ | |
237 | new = copy_node (type); | |
5e20bdd7 | 238 | insert_decl_map (id, type, new); |
3c2a7a6a RH |
239 | |
240 | /* This is a new type, not a copy of an old type. Need to reassociate | |
241 | variants. We can handle everything except the main variant lazily. */ | |
242 | t = TYPE_MAIN_VARIANT (type); | |
243 | if (type != t) | |
244 | { | |
245 | t = remap_type (t, id); | |
246 | TYPE_MAIN_VARIANT (new) = t; | |
247 | TYPE_NEXT_VARIANT (new) = TYPE_MAIN_VARIANT (t); | |
248 | TYPE_NEXT_VARIANT (t) = new; | |
249 | } | |
250 | else | |
251 | { | |
252 | TYPE_MAIN_VARIANT (new) = new; | |
253 | TYPE_NEXT_VARIANT (new) = NULL; | |
254 | } | |
255 | ||
256 | /* Lazily create pointer and reference types. */ | |
257 | TYPE_POINTER_TO (new) = NULL; | |
258 | TYPE_REFERENCE_TO (new) = NULL; | |
259 | ||
260 | switch (TREE_CODE (new)) | |
261 | { | |
262 | case INTEGER_TYPE: | |
263 | case REAL_TYPE: | |
264 | case ENUMERAL_TYPE: | |
265 | case BOOLEAN_TYPE: | |
266 | case CHAR_TYPE: | |
267 | t = TYPE_MIN_VALUE (new); | |
268 | if (t && TREE_CODE (t) != INTEGER_CST) | |
269 | walk_tree (&TYPE_MIN_VALUE (new), copy_body_r, id, NULL); | |
270 | t = TYPE_MAX_VALUE (new); | |
271 | if (t && TREE_CODE (t) != INTEGER_CST) | |
272 | walk_tree (&TYPE_MAX_VALUE (new), copy_body_r, id, NULL); | |
273 | return new; | |
274 | ||
275 | case POINTER_TYPE: | |
276 | TREE_TYPE (new) = t = remap_type (TREE_TYPE (new), id); | |
277 | if (TYPE_MODE (new) == ptr_mode) | |
278 | TYPE_POINTER_TO (t) = new; | |
279 | return new; | |
280 | ||
281 | case REFERENCE_TYPE: | |
282 | TREE_TYPE (new) = t = remap_type (TREE_TYPE (new), id); | |
283 | if (TYPE_MODE (new) == ptr_mode) | |
284 | TYPE_REFERENCE_TO (t) = new; | |
285 | return new; | |
286 | ||
287 | case METHOD_TYPE: | |
288 | case FUNCTION_TYPE: | |
289 | TREE_TYPE (new) = remap_type (TREE_TYPE (new), id); | |
290 | walk_tree (&TYPE_ARG_TYPES (new), copy_body_r, id, NULL); | |
291 | return new; | |
292 | ||
293 | case ARRAY_TYPE: | |
294 | TREE_TYPE (new) = remap_type (TREE_TYPE (new), id); | |
295 | TYPE_DOMAIN (new) = remap_type (TYPE_DOMAIN (new), id); | |
296 | break; | |
297 | ||
298 | case RECORD_TYPE: | |
299 | case UNION_TYPE: | |
300 | case QUAL_UNION_TYPE: | |
301 | walk_tree (&TYPE_FIELDS (new), copy_body_r, id, NULL); | |
302 | break; | |
303 | ||
304 | case FILE_TYPE: | |
305 | case SET_TYPE: | |
306 | case OFFSET_TYPE: | |
307 | default: | |
308 | /* Shouldn't have been thought variable sized. */ | |
309 | abort (); | |
310 | } | |
311 | ||
312 | walk_tree (&TYPE_SIZE (new), copy_body_r, id, NULL); | |
313 | walk_tree (&TYPE_SIZE_UNIT (new), copy_body_r, id, NULL); | |
314 | ||
315 | return new; | |
316 | } | |
317 | ||
d436bff8 | 318 | #ifndef INLINER_FOR_JAVA |
d4e4baa9 AO |
319 | /* Copy the SCOPE_STMT_BLOCK associated with SCOPE_STMT to contain |
320 | remapped versions of the variables therein. And hook the new block | |
321 | into the block-tree. If non-NULL, the DECLS are declarations to | |
322 | add to use instead of the BLOCK_VARS in the old block. */ | |
d436bff8 AH |
323 | #else /* INLINER_FOR_JAVA */ |
324 | /* Copy the BLOCK to contain remapped versions of the variables | |
325 | therein. And hook the new block into the block-tree. */ | |
326 | #endif /* INLINER_FOR_JAVA */ | |
d4e4baa9 AO |
327 | |
328 | static void | |
d436bff8 | 329 | #ifndef INLINER_FOR_JAVA |
46c5ad27 | 330 | remap_block (tree scope_stmt, tree decls, inline_data *id) |
d436bff8 | 331 | #else /* INLINER_FOR_JAVA */ |
46c5ad27 | 332 | remap_block (tree *block, tree decls, inline_data *id) |
d436bff8 | 333 | #endif /* INLINER_FOR_JAVA */ |
d4e4baa9 | 334 | { |
d436bff8 | 335 | #ifndef INLINER_FOR_JAVA |
d4e4baa9 AO |
336 | /* We cannot do this in the cleanup for a TARGET_EXPR since we do |
337 | not know whether or not expand_expr will actually write out the | |
338 | code we put there. If it does not, then we'll have more BLOCKs | |
339 | than block-notes, and things will go awry. At some point, we | |
340 | should make the back-end handle BLOCK notes in a tidier way, | |
341 | without requiring a strict correspondence to the block-tree; then | |
342 | this check can go. */ | |
343 | if (id->in_target_cleanup_p) | |
344 | { | |
345 | SCOPE_STMT_BLOCK (scope_stmt) = NULL_TREE; | |
346 | return; | |
347 | } | |
348 | ||
349 | /* If this is the beginning of a scope, remap the associated BLOCK. */ | |
350 | if (SCOPE_BEGIN_P (scope_stmt) && SCOPE_STMT_BLOCK (scope_stmt)) | |
351 | { | |
352 | tree old_block; | |
353 | tree new_block; | |
354 | tree old_var; | |
355 | tree fn; | |
356 | ||
357 | /* Make the new block. */ | |
358 | old_block = SCOPE_STMT_BLOCK (scope_stmt); | |
359 | new_block = make_node (BLOCK); | |
360 | TREE_USED (new_block) = TREE_USED (old_block); | |
361 | BLOCK_ABSTRACT_ORIGIN (new_block) = old_block; | |
362 | SCOPE_STMT_BLOCK (scope_stmt) = new_block; | |
363 | ||
364 | /* Remap its variables. */ | |
365 | for (old_var = decls ? decls : BLOCK_VARS (old_block); | |
366 | old_var; | |
367 | old_var = TREE_CHAIN (old_var)) | |
368 | { | |
369 | tree new_var; | |
370 | ||
371 | /* Remap the variable. */ | |
372 | new_var = remap_decl (old_var, id); | |
373 | /* If we didn't remap this variable, so we can't mess with | |
374 | its TREE_CHAIN. If we remapped this variable to | |
375 | something other than a declaration (say, if we mapped it | |
376 | to a constant), then we must similarly omit any mention | |
377 | of it here. */ | |
378 | if (!new_var || !DECL_P (new_var)) | |
379 | ; | |
380 | else | |
381 | { | |
382 | TREE_CHAIN (new_var) = BLOCK_VARS (new_block); | |
383 | BLOCK_VARS (new_block) = new_var; | |
384 | } | |
385 | } | |
386 | /* We put the BLOCK_VARS in reverse order; fix that now. */ | |
387 | BLOCK_VARS (new_block) = nreverse (BLOCK_VARS (new_block)); | |
388 | fn = VARRAY_TREE (id->fns, 0); | |
389 | if (id->cloning_p) | |
390 | /* We're building a clone; DECL_INITIAL is still | |
391 | error_mark_node, and current_binding_level is the parm | |
392 | binding level. */ | |
43577e6b | 393 | (*lang_hooks.decls.insert_block) (new_block); |
d4e4baa9 AO |
394 | else |
395 | { | |
396 | /* Attach this new block after the DECL_INITIAL block for the | |
397 | function into which this block is being inlined. In | |
398 | rest_of_compilation we will straighten out the BLOCK tree. */ | |
399 | tree *first_block; | |
400 | if (DECL_INITIAL (fn)) | |
401 | first_block = &BLOCK_CHAIN (DECL_INITIAL (fn)); | |
402 | else | |
403 | first_block = &DECL_INITIAL (fn); | |
404 | BLOCK_CHAIN (new_block) = *first_block; | |
405 | *first_block = new_block; | |
406 | } | |
407 | /* Remember the remapped block. */ | |
5e20bdd7 | 408 | insert_decl_map (id, old_block, new_block); |
d4e4baa9 AO |
409 | } |
410 | /* If this is the end of a scope, set the SCOPE_STMT_BLOCK to be the | |
411 | remapped block. */ | |
412 | else if (SCOPE_END_P (scope_stmt) && SCOPE_STMT_BLOCK (scope_stmt)) | |
413 | { | |
414 | splay_tree_node n; | |
415 | ||
416 | /* Find this block in the table of remapped things. */ | |
417 | n = splay_tree_lookup (id->decl_map, | |
418 | (splay_tree_key) SCOPE_STMT_BLOCK (scope_stmt)); | |
419 | if (! n) | |
420 | abort (); | |
421 | SCOPE_STMT_BLOCK (scope_stmt) = (tree) n->value; | |
422 | } | |
d436bff8 AH |
423 | #else /* INLINER_FOR_JAVA */ |
424 | tree old_block; | |
425 | tree new_block; | |
426 | tree old_var; | |
427 | tree fn; | |
428 | ||
429 | /* Make the new block. */ | |
430 | old_block = *block; | |
431 | new_block = make_node (BLOCK); | |
432 | TREE_USED (new_block) = TREE_USED (old_block); | |
433 | BLOCK_ABSTRACT_ORIGIN (new_block) = old_block; | |
434 | BLOCK_SUBBLOCKS (new_block) = BLOCK_SUBBLOCKS (old_block); | |
435 | TREE_SIDE_EFFECTS (new_block) = TREE_SIDE_EFFECTS (old_block); | |
436 | TREE_TYPE (new_block) = TREE_TYPE (old_block); | |
437 | *block = new_block; | |
438 | ||
439 | /* Remap its variables. */ | |
440 | for (old_var = decls ? decls : BLOCK_VARS (old_block); | |
441 | old_var; | |
442 | old_var = TREE_CHAIN (old_var)) | |
443 | { | |
444 | tree new_var; | |
445 | ||
3eb429b2 AH |
446 | /* All local class initialization flags go in the outermost |
447 | scope. */ | |
448 | if (LOCAL_CLASS_INITIALIZATION_FLAG_P (old_var)) | |
449 | { | |
450 | /* We may already have one. */ | |
451 | if (! splay_tree_lookup (id->decl_map, (splay_tree_key) old_var)) | |
452 | { | |
453 | tree outermost_block; | |
454 | new_var = remap_decl (old_var, id); | |
455 | DECL_ABSTRACT_ORIGIN (new_var) = NULL; | |
456 | outermost_block = DECL_SAVED_TREE (current_function_decl); | |
457 | TREE_CHAIN (new_var) = BLOCK_VARS (outermost_block); | |
458 | BLOCK_VARS (outermost_block) = new_var; | |
459 | } | |
460 | continue; | |
461 | } | |
462 | ||
d436bff8 AH |
463 | /* Remap the variable. */ |
464 | new_var = remap_decl (old_var, id); | |
465 | /* If we didn't remap this variable, so we can't mess with | |
466 | its TREE_CHAIN. If we remapped this variable to | |
467 | something other than a declaration (say, if we mapped it | |
468 | to a constant), then we must similarly omit any mention | |
469 | of it here. */ | |
470 | if (!new_var || !DECL_P (new_var)) | |
471 | ; | |
472 | else | |
473 | { | |
474 | TREE_CHAIN (new_var) = BLOCK_VARS (new_block); | |
475 | BLOCK_VARS (new_block) = new_var; | |
476 | } | |
477 | } | |
478 | /* We put the BLOCK_VARS in reverse order; fix that now. */ | |
479 | BLOCK_VARS (new_block) = nreverse (BLOCK_VARS (new_block)); | |
480 | fn = VARRAY_TREE (id->fns, 0); | |
481 | /* Remember the remapped block. */ | |
482 | splay_tree_insert (id->decl_map, | |
483 | (splay_tree_key) old_block, | |
484 | (splay_tree_value) new_block); | |
485 | #endif /* INLINER_FOR_JAVA */ | |
d4e4baa9 AO |
486 | } |
487 | ||
d436bff8 | 488 | #ifndef INLINER_FOR_JAVA |
d4e4baa9 AO |
489 | /* Copy the SCOPE_STMT pointed to by TP. */ |
490 | ||
491 | static void | |
46c5ad27 | 492 | copy_scope_stmt (tree *tp, int *walk_subtrees, inline_data *id) |
d4e4baa9 AO |
493 | { |
494 | tree block; | |
495 | ||
496 | /* Remember whether or not this statement was nullified. When | |
497 | making a copy, copy_tree_r always sets SCOPE_NULLIFIED_P (and | |
498 | doesn't copy the SCOPE_STMT_BLOCK) to free callers from having to | |
499 | deal with copying BLOCKs if they do not wish to do so. */ | |
500 | block = SCOPE_STMT_BLOCK (*tp); | |
501 | /* Copy (and replace) the statement. */ | |
502 | copy_tree_r (tp, walk_subtrees, NULL); | |
503 | /* Restore the SCOPE_STMT_BLOCK. */ | |
504 | SCOPE_STMT_BLOCK (*tp) = block; | |
505 | ||
506 | /* Remap the associated block. */ | |
507 | remap_block (*tp, NULL_TREE, id); | |
508 | } | |
d436bff8 | 509 | #endif /* not INLINER_FOR_JAVA */ |
d4e4baa9 AO |
510 | |
511 | /* Called from copy_body via walk_tree. DATA is really an | |
512 | `inline_data *'. */ | |
d4e4baa9 | 513 | static tree |
46c5ad27 | 514 | copy_body_r (tree *tp, int *walk_subtrees, void *data) |
d4e4baa9 AO |
515 | { |
516 | inline_data* id; | |
517 | tree fn; | |
518 | ||
519 | /* Set up. */ | |
520 | id = (inline_data *) data; | |
521 | fn = VARRAY_TOP_TREE (id->fns); | |
522 | ||
523 | #if 0 | |
524 | /* All automatic variables should have a DECL_CONTEXT indicating | |
525 | what function they come from. */ | |
526 | if ((TREE_CODE (*tp) == VAR_DECL || TREE_CODE (*tp) == LABEL_DECL) | |
527 | && DECL_NAMESPACE_SCOPE_P (*tp)) | |
528 | if (! DECL_EXTERNAL (*tp) && ! TREE_STATIC (*tp)) | |
529 | abort (); | |
530 | #endif | |
531 | ||
d436bff8 AH |
532 | #ifdef INLINER_FOR_JAVA |
533 | if (TREE_CODE (*tp) == BLOCK) | |
534 | remap_block (tp, NULL_TREE, id); | |
535 | #endif | |
536 | ||
d4e4baa9 AO |
537 | /* If this is a RETURN_STMT, change it into an EXPR_STMT and a |
538 | GOTO_STMT with the RET_LABEL as its target. */ | |
d436bff8 | 539 | #ifndef INLINER_FOR_JAVA |
d4e4baa9 | 540 | if (TREE_CODE (*tp) == RETURN_STMT && id->ret_label) |
d436bff8 AH |
541 | #else /* INLINER_FOR_JAVA */ |
542 | if (TREE_CODE (*tp) == RETURN_EXPR && id->ret_label) | |
543 | #endif /* INLINER_FOR_JAVA */ | |
d4e4baa9 AO |
544 | { |
545 | tree return_stmt = *tp; | |
546 | tree goto_stmt; | |
547 | ||
548 | /* Build the GOTO_STMT. */ | |
d436bff8 | 549 | #ifndef INLINER_FOR_JAVA |
d4e4baa9 AO |
550 | goto_stmt = build_stmt (GOTO_STMT, id->ret_label); |
551 | TREE_CHAIN (goto_stmt) = TREE_CHAIN (return_stmt); | |
db4a8254 | 552 | GOTO_FAKE_P (goto_stmt) = 1; |
d436bff8 AH |
553 | #else /* INLINER_FOR_JAVA */ |
554 | tree assignment = TREE_OPERAND (return_stmt, 0); | |
555 | goto_stmt = build1 (GOTO_EXPR, void_type_node, id->ret_label); | |
556 | TREE_SIDE_EFFECTS (goto_stmt) = 1; | |
557 | #endif /* INLINER_FOR_JAVA */ | |
d4e4baa9 AO |
558 | |
559 | /* If we're returning something, just turn that into an | |
560 | assignment into the equivalent of the original | |
561 | RESULT_DECL. */ | |
d436bff8 | 562 | #ifndef INLINER_FOR_JAVA |
d65b1d77 | 563 | if (RETURN_STMT_EXPR (return_stmt)) |
d4e4baa9 AO |
564 | { |
565 | *tp = build_stmt (EXPR_STMT, | |
d65b1d77 | 566 | RETURN_STMT_EXPR (return_stmt)); |
d4e4baa9 AO |
567 | STMT_IS_FULL_EXPR_P (*tp) = 1; |
568 | /* And then jump to the end of the function. */ | |
569 | TREE_CHAIN (*tp) = goto_stmt; | |
570 | } | |
d436bff8 AH |
571 | #else /* INLINER_FOR_JAVA */ |
572 | if (assignment) | |
573 | { | |
574 | copy_body_r (&assignment, walk_subtrees, data); | |
575 | *tp = build (COMPOUND_EXPR, void_type_node, assignment, goto_stmt); | |
50aadcbc | 576 | TREE_SIDE_EFFECTS (*tp) = 1; |
d436bff8 AH |
577 | } |
578 | #endif /* INLINER_FOR_JAVA */ | |
d4e4baa9 AO |
579 | /* If we're not returning anything just do the jump. */ |
580 | else | |
581 | *tp = goto_stmt; | |
5e20bdd7 JZ |
582 | |
583 | /* We can't replace return label while inlining function | |
584 | because it is in the outer function. */ | |
585 | insert_decl_map (id, id->ret_label, id->ret_label); | |
d4e4baa9 AO |
586 | } |
587 | /* Local variables and labels need to be replaced by equivalent | |
588 | variables. We don't want to copy static variables; there's only | |
589 | one of those, no matter how many times we inline the containing | |
5e20bdd7 JZ |
590 | function. */ |
591 | else if ((*lang_hooks.tree_inlining.auto_var_in_fn_p) (*tp, fn)) | |
d4e4baa9 AO |
592 | { |
593 | tree new_decl; | |
594 | ||
595 | /* Remap the declaration. */ | |
596 | new_decl = remap_decl (*tp, id); | |
597 | if (! new_decl) | |
598 | abort (); | |
599 | /* Replace this variable with the copy. */ | |
600 | STRIP_TYPE_NOPS (new_decl); | |
601 | *tp = new_decl; | |
602 | } | |
603 | #if 0 | |
604 | else if (nonstatic_local_decl_p (*tp) | |
605 | && DECL_CONTEXT (*tp) != VARRAY_TREE (id->fns, 0)) | |
606 | abort (); | |
607 | #endif | |
608 | else if (TREE_CODE (*tp) == SAVE_EXPR) | |
609 | remap_save_expr (tp, id->decl_map, VARRAY_TREE (id->fns, 0), | |
610 | walk_subtrees); | |
611 | else if (TREE_CODE (*tp) == UNSAVE_EXPR) | |
612 | /* UNSAVE_EXPRs should not be generated until expansion time. */ | |
613 | abort (); | |
d436bff8 | 614 | #ifndef INLINER_FOR_JAVA |
d4e4baa9 AO |
615 | /* For a SCOPE_STMT, we must copy the associated block so that we |
616 | can write out debugging information for the inlined variables. */ | |
617 | else if (TREE_CODE (*tp) == SCOPE_STMT && !id->in_target_cleanup_p) | |
618 | copy_scope_stmt (tp, walk_subtrees, id); | |
d436bff8 AH |
619 | #else /* INLINER_FOR_JAVA */ |
620 | else if (TREE_CODE (*tp) == LABELED_BLOCK_EXPR) | |
621 | { | |
622 | /* We need a new copy of this labeled block; the EXIT_BLOCK_EXPR | |
623 | will refer to it, so save a copy ready for remapping. We | |
624 | save it in the decl_map, although it isn't a decl. */ | |
625 | tree new_block = copy_node (*tp); | |
5e20bdd7 | 626 | insert_decl_map (id, *tp, new_block); |
d436bff8 AH |
627 | *tp = new_block; |
628 | } | |
629 | else if (TREE_CODE (*tp) == EXIT_BLOCK_EXPR) | |
630 | { | |
50aadcbc AJ |
631 | splay_tree_node n |
632 | = splay_tree_lookup (id->decl_map, | |
d436bff8 AH |
633 | (splay_tree_key) TREE_OPERAND (*tp, 0)); |
634 | /* We _must_ have seen the enclosing LABELED_BLOCK_EXPR. */ | |
635 | if (! n) | |
636 | abort (); | |
637 | *tp = copy_node (*tp); | |
638 | TREE_OPERAND (*tp, 0) = (tree) n->value; | |
639 | } | |
640 | #endif /* INLINER_FOR_JAVA */ | |
3c2a7a6a RH |
641 | /* Types may need remapping as well. */ |
642 | else if (TYPE_P (*tp)) | |
643 | *tp = remap_type (*tp, id); | |
644 | ||
d4e4baa9 AO |
645 | /* Otherwise, just copy the node. Note that copy_tree_r already |
646 | knows not to copy VAR_DECLs, etc., so this is safe. */ | |
647 | else | |
648 | { | |
68594ce7 JM |
649 | if (TREE_CODE (*tp) == MODIFY_EXPR |
650 | && TREE_OPERAND (*tp, 0) == TREE_OPERAND (*tp, 1) | |
651 | && ((*lang_hooks.tree_inlining.auto_var_in_fn_p) | |
652 | (TREE_OPERAND (*tp, 0), fn))) | |
d4e4baa9 AO |
653 | { |
654 | /* Some assignments VAR = VAR; don't generate any rtl code | |
655 | and thus don't count as variable modification. Avoid | |
656 | keeping bogosities like 0 = 0. */ | |
657 | tree decl = TREE_OPERAND (*tp, 0), value; | |
658 | splay_tree_node n; | |
659 | ||
660 | n = splay_tree_lookup (id->decl_map, (splay_tree_key) decl); | |
661 | if (n) | |
662 | { | |
663 | value = (tree) n->value; | |
664 | STRIP_TYPE_NOPS (value); | |
665 | if (TREE_CONSTANT (value) || TREE_READONLY_DECL_P (value)) | |
68594ce7 JM |
666 | { |
667 | *tp = value; | |
668 | return copy_body_r (tp, walk_subtrees, data); | |
669 | } | |
d4e4baa9 AO |
670 | } |
671 | } | |
68594ce7 JM |
672 | else if (TREE_CODE (*tp) == ADDR_EXPR |
673 | && ((*lang_hooks.tree_inlining.auto_var_in_fn_p) | |
674 | (TREE_OPERAND (*tp, 0), fn))) | |
675 | { | |
676 | /* Get rid of &* from inline substitutions. It can occur when | |
677 | someone takes the address of a parm or return slot passed by | |
678 | invisible reference. */ | |
679 | tree decl = TREE_OPERAND (*tp, 0), value; | |
680 | splay_tree_node n; | |
681 | ||
682 | n = splay_tree_lookup (id->decl_map, (splay_tree_key) decl); | |
683 | if (n) | |
684 | { | |
685 | value = (tree) n->value; | |
686 | if (TREE_CODE (value) == INDIRECT_REF) | |
687 | { | |
688 | *tp = convert (TREE_TYPE (*tp), TREE_OPERAND (value, 0)); | |
689 | return copy_body_r (tp, walk_subtrees, data); | |
690 | } | |
691 | } | |
692 | } | |
693 | ||
694 | copy_tree_r (tp, walk_subtrees, NULL); | |
695 | ||
3c2a7a6a RH |
696 | TREE_TYPE (*tp) = remap_type (TREE_TYPE (*tp), id); |
697 | ||
68594ce7 JM |
698 | /* The copied TARGET_EXPR has never been expanded, even if the |
699 | original node was expanded already. */ | |
700 | if (TREE_CODE (*tp) == TARGET_EXPR && TREE_OPERAND (*tp, 3)) | |
701 | { | |
702 | TREE_OPERAND (*tp, 1) = TREE_OPERAND (*tp, 3); | |
703 | TREE_OPERAND (*tp, 3) = NULL_TREE; | |
704 | } | |
d4e4baa9 AO |
705 | } |
706 | ||
707 | /* Keep iterating. */ | |
708 | return NULL_TREE; | |
709 | } | |
710 | ||
711 | /* Make a copy of the body of FN so that it can be inserted inline in | |
712 | another function. */ | |
713 | ||
714 | static tree | |
46c5ad27 | 715 | copy_body (inline_data *id) |
d4e4baa9 AO |
716 | { |
717 | tree body; | |
718 | ||
719 | body = DECL_SAVED_TREE (VARRAY_TOP_TREE (id->fns)); | |
720 | walk_tree (&body, copy_body_r, id, NULL); | |
721 | ||
722 | return body; | |
723 | } | |
724 | ||
725 | /* Generate code to initialize the parameters of the function at the | |
726 | top of the stack in ID from the ARGS (presented as a TREE_LIST). */ | |
727 | ||
728 | static tree | |
d436bff8 | 729 | #ifndef INLINER_FOR_JAVA |
46c5ad27 | 730 | initialize_inlined_parameters (inline_data *id, tree args, tree fn) |
d436bff8 | 731 | #else /* INLINER_FOR_JAVA */ |
46c5ad27 | 732 | initialize_inlined_parameters (inline_data *id, tree args, tree fn, tree block) |
d436bff8 | 733 | #endif /* INLINER_FOR_JAVA */ |
d4e4baa9 AO |
734 | { |
735 | tree init_stmts; | |
736 | tree parms; | |
737 | tree a; | |
738 | tree p; | |
d436bff8 AH |
739 | #ifdef INLINER_FOR_JAVA |
740 | tree vars = NULL_TREE; | |
741 | #endif /* INLINER_FOR_JAVA */ | |
d5123bae | 742 | int argnum = 0; |
d4e4baa9 AO |
743 | |
744 | /* Figure out what the parameters are. */ | |
d5123bae MS |
745 | parms = |
746 | DECL_ARGUMENTS (fn); | |
d4e4baa9 AO |
747 | |
748 | /* Start with no initializations whatsoever. */ | |
749 | init_stmts = NULL_TREE; | |
750 | ||
751 | /* Loop through the parameter declarations, replacing each with an | |
752 | equivalent VAR_DECL, appropriately initialized. */ | |
4838c5ee AO |
753 | for (p = parms, a = args; p; |
754 | a = a ? TREE_CHAIN (a) : a, p = TREE_CHAIN (p)) | |
d4e4baa9 | 755 | { |
d436bff8 | 756 | #ifndef INLINER_FOR_JAVA |
d4e4baa9 | 757 | tree init_stmt; |
9bc146b3 | 758 | tree cleanup; |
d436bff8 | 759 | #endif /* not INLINER_FOR_JAVA */ |
d4e4baa9 AO |
760 | tree var; |
761 | tree value; | |
c246c65d | 762 | tree var_sub; |
d4e4baa9 | 763 | |
d5123bae MS |
764 | ++argnum; |
765 | ||
d4e4baa9 | 766 | /* Find the initializer. */ |
f735a153 | 767 | value = (*lang_hooks.tree_inlining.convert_parm_for_inlining) |
d5123bae | 768 | (p, a ? TREE_VALUE (a) : NULL_TREE, fn, argnum); |
4838c5ee | 769 | |
d4e4baa9 AO |
770 | /* If the parameter is never assigned to, we may not need to |
771 | create a new variable here at all. Instead, we may be able | |
772 | to just use the argument value. */ | |
773 | if (TREE_READONLY (p) | |
774 | && !TREE_ADDRESSABLE (p) | |
4838c5ee | 775 | && value && !TREE_SIDE_EFFECTS (value)) |
d4e4baa9 AO |
776 | { |
777 | /* Simplify the value, if possible. */ | |
4838c5ee | 778 | value = fold (DECL_P (value) ? decl_constant_value (value) : value); |
d4e4baa9 AO |
779 | |
780 | /* We can't risk substituting complex expressions. They | |
781 | might contain variables that will be assigned to later. | |
782 | Theoretically, we could check the expression to see if | |
783 | all of the variables that determine its value are | |
784 | read-only, but we don't bother. */ | |
785 | if (TREE_CONSTANT (value) || TREE_READONLY_DECL_P (value)) | |
786 | { | |
787 | /* If this is a declaration, wrap it a NOP_EXPR so that | |
788 | we don't try to put the VALUE on the list of | |
789 | BLOCK_VARS. */ | |
790 | if (DECL_P (value)) | |
791 | value = build1 (NOP_EXPR, TREE_TYPE (value), value); | |
792 | ||
f650843f EB |
793 | /* If this is a constant, make sure it has the right type. */ |
794 | else if (TREE_TYPE (value) != TREE_TYPE (p)) | |
795 | value = fold (build1 (NOP_EXPR, TREE_TYPE (p), value)); | |
796 | ||
5e20bdd7 | 797 | insert_decl_map (id, p, value); |
d4e4baa9 AO |
798 | continue; |
799 | } | |
800 | } | |
801 | ||
802 | /* Make an equivalent VAR_DECL. */ | |
803 | var = copy_decl_for_inlining (p, fn, VARRAY_TREE (id->fns, 0)); | |
c246c65d JM |
804 | |
805 | /* See if the frontend wants to pass this by invisible reference. If | |
806 | so, our new VAR_DECL will have REFERENCE_TYPE, and we need to | |
807 | replace uses of the PARM_DECL with dereferences. */ | |
808 | if (TREE_TYPE (var) != TREE_TYPE (p) | |
809 | && POINTER_TYPE_P (TREE_TYPE (var)) | |
810 | && TREE_TYPE (TREE_TYPE (var)) == TREE_TYPE (p)) | |
811 | var_sub = build1 (INDIRECT_REF, TREE_TYPE (p), var); | |
812 | else | |
813 | var_sub = var; | |
814 | ||
d4e4baa9 AO |
815 | /* Register the VAR_DECL as the equivalent for the PARM_DECL; |
816 | that way, when the PARM_DECL is encountered, it will be | |
817 | automatically replaced by the VAR_DECL. */ | |
5e20bdd7 | 818 | insert_decl_map (id, p, var_sub); |
d4e4baa9 AO |
819 | |
820 | /* Declare this new variable. */ | |
d436bff8 | 821 | #ifndef INLINER_FOR_JAVA |
d4e4baa9 AO |
822 | init_stmt = build_stmt (DECL_STMT, var); |
823 | TREE_CHAIN (init_stmt) = init_stmts; | |
824 | init_stmts = init_stmt; | |
d436bff8 AH |
825 | #else /* INLINER_FOR_JAVA */ |
826 | TREE_CHAIN (var) = vars; | |
827 | vars = var; | |
828 | #endif /* INLINER_FOR_JAVA */ | |
d4e4baa9 AO |
829 | |
830 | /* Initialize this VAR_DECL from the equivalent argument. If | |
831 | the argument is an object, created via a constructor or copy, | |
832 | this will not result in an extra copy: the TARGET_EXPR | |
833 | representing the argument will be bound to VAR, and the | |
834 | object will be constructed in VAR. */ | |
835 | if (! TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (p))) | |
d436bff8 | 836 | #ifndef INLINER_FOR_JAVA |
d4e4baa9 AO |
837 | DECL_INITIAL (var) = value; |
838 | else | |
839 | { | |
840 | /* Even if P was TREE_READONLY, the new VAR should not be. | |
841 | In the original code, we would have constructed a | |
842 | temporary, and then the function body would have never | |
843 | changed the value of P. However, now, we will be | |
844 | constructing VAR directly. The constructor body may | |
845 | change its value multiple times as it is being | |
846 | constructed. Therefore, it must not be TREE_READONLY; | |
847 | the back-end assumes that TREE_READONLY variable is | |
848 | assigned to only once. */ | |
849 | TREE_READONLY (var) = 0; | |
850 | ||
851 | /* Build a run-time initialization. */ | |
852 | init_stmt = build_stmt (EXPR_STMT, | |
853 | build (INIT_EXPR, TREE_TYPE (p), | |
854 | var, value)); | |
855 | /* Add this initialization to the list. Note that we want the | |
856 | declaration *after* the initialization because we are going | |
857 | to reverse all the initialization statements below. */ | |
858 | TREE_CHAIN (init_stmt) = init_stmts; | |
859 | init_stmts = init_stmt; | |
860 | } | |
6e4ae815 MM |
861 | |
862 | /* See if we need to clean up the declaration. */ | |
c88770e9 | 863 | cleanup = (*lang_hooks.maybe_build_cleanup) (var); |
d92b4486 | 864 | if (cleanup) |
6e4ae815 MM |
865 | { |
866 | tree cleanup_stmt; | |
867 | /* Build the cleanup statement. */ | |
868 | cleanup_stmt = build_stmt (CLEANUP_STMT, var, cleanup); | |
869 | /* Add it to the *front* of the list; the list will be | |
870 | reversed below. */ | |
871 | TREE_CHAIN (cleanup_stmt) = init_stmts; | |
872 | init_stmts = cleanup_stmt; | |
873 | } | |
d436bff8 AH |
874 | #else /* INLINER_FOR_JAVA */ |
875 | { | |
876 | tree assignment = build (MODIFY_EXPR, TREE_TYPE (p), var, value); | |
50aadcbc | 877 | init_stmts = add_stmt_to_compound (init_stmts, TREE_TYPE (p), |
d436bff8 AH |
878 | assignment); |
879 | } | |
880 | else | |
881 | { | |
882 | /* Java objects don't ever need constructing when being | |
883 | passed as arguments because only call by reference is | |
884 | supported. */ | |
885 | abort (); | |
886 | } | |
887 | #endif /* INLINER_FOR_JAVA */ | |
d4e4baa9 AO |
888 | } |
889 | ||
d436bff8 | 890 | #ifndef INLINER_FOR_JAVA |
4838c5ee AO |
891 | /* Evaluate trailing arguments. */ |
892 | for (; a; a = TREE_CHAIN (a)) | |
893 | { | |
894 | tree init_stmt; | |
6e4ae815 | 895 | tree value = TREE_VALUE (a); |
4838c5ee AO |
896 | |
897 | if (! value || ! TREE_SIDE_EFFECTS (value)) | |
898 | continue; | |
899 | ||
900 | init_stmt = build_stmt (EXPR_STMT, value); | |
901 | TREE_CHAIN (init_stmt) = init_stmts; | |
902 | init_stmts = init_stmt; | |
903 | } | |
904 | ||
d4e4baa9 AO |
905 | /* The initialization statements have been built up in reverse |
906 | order. Straighten them out now. */ | |
907 | return nreverse (init_stmts); | |
d436bff8 AH |
908 | #else /* INLINER_FOR_JAVA */ |
909 | BLOCK_VARS (block) = nreverse (vars); | |
910 | return init_stmts; | |
911 | #endif /* INLINER_FOR_JAVA */ | |
d4e4baa9 AO |
912 | } |
913 | ||
914 | /* Declare a return variable to replace the RESULT_DECL for the | |
915 | function we are calling. An appropriate DECL_STMT is returned. | |
916 | The USE_STMT is filled in to contain a use of the declaration to | |
917 | indicate the return value of the function. */ | |
918 | ||
d436bff8 | 919 | #ifndef INLINER_FOR_JAVA |
d4e4baa9 | 920 | static tree |
46c5ad27 AJ |
921 | declare_return_variable (struct inline_data *id, tree return_slot_addr, |
922 | tree *use_stmt) | |
d436bff8 AH |
923 | #else /* INLINER_FOR_JAVA */ |
924 | static tree | |
46c5ad27 AJ |
925 | declare_return_variable (struct inline_data *id, tree return_slot_addr, |
926 | tree *var) | |
d436bff8 | 927 | #endif /* INLINER_FOR_JAVA */ |
d4e4baa9 AO |
928 | { |
929 | tree fn = VARRAY_TOP_TREE (id->fns); | |
930 | tree result = DECL_RESULT (fn); | |
d436bff8 | 931 | #ifndef INLINER_FOR_JAVA |
d4e4baa9 | 932 | tree var; |
d436bff8 | 933 | #endif /* not INLINER_FOR_JAVA */ |
d4e4baa9 AO |
934 | int need_return_decl = 1; |
935 | ||
936 | /* We don't need to do anything for functions that don't return | |
937 | anything. */ | |
938 | if (!result || VOID_TYPE_P (TREE_TYPE (result))) | |
939 | { | |
d436bff8 | 940 | #ifndef INLINER_FOR_JAVA |
d4e4baa9 | 941 | *use_stmt = NULL_TREE; |
d436bff8 AH |
942 | #else /* INLINER_FOR_JAVA */ |
943 | *var = NULL_TREE; | |
944 | #endif /* INLINER_FOR_JAVA */ | |
d4e4baa9 AO |
945 | return NULL_TREE; |
946 | } | |
947 | ||
d436bff8 | 948 | #ifndef INLINER_FOR_JAVA |
69dcadff AO |
949 | var = ((*lang_hooks.tree_inlining.copy_res_decl_for_inlining) |
950 | (result, fn, VARRAY_TREE (id->fns, 0), id->decl_map, | |
4977bab6 | 951 | &need_return_decl, return_slot_addr)); |
d4e4baa9 AO |
952 | |
953 | /* Register the VAR_DECL as the equivalent for the RESULT_DECL; that | |
954 | way, when the RESULT_DECL is encountered, it will be | |
955 | automatically replaced by the VAR_DECL. */ | |
5e20bdd7 | 956 | insert_decl_map (id, result, var); |
d4e4baa9 | 957 | |
4838c5ee AO |
958 | /* Build the USE_STMT. If the return type of the function was |
959 | promoted, convert it back to the expected type. */ | |
960 | if (TREE_TYPE (var) == TREE_TYPE (TREE_TYPE (fn))) | |
961 | *use_stmt = build_stmt (EXPR_STMT, var); | |
962 | else | |
963 | *use_stmt = build_stmt (EXPR_STMT, | |
964 | build1 (NOP_EXPR, TREE_TYPE (TREE_TYPE (fn)), | |
965 | var)); | |
1574ef13 AO |
966 | TREE_ADDRESSABLE (*use_stmt) = 1; |
967 | ||
d4e4baa9 AO |
968 | /* Build the declaration statement if FN does not return an |
969 | aggregate. */ | |
970 | if (need_return_decl) | |
971 | return build_stmt (DECL_STMT, var); | |
d436bff8 AH |
972 | #else /* INLINER_FOR_JAVA */ |
973 | *var = ((*lang_hooks.tree_inlining.copy_res_decl_for_inlining) | |
974 | (result, fn, VARRAY_TREE (id->fns, 0), id->decl_map, | |
4977bab6 | 975 | &need_return_decl, return_slot_addr)); |
d436bff8 AH |
976 | |
977 | splay_tree_insert (id->decl_map, | |
978 | (splay_tree_key) result, | |
979 | (splay_tree_value) *var); | |
980 | DECL_IGNORED_P (*var) = 1; | |
981 | if (need_return_decl) | |
982 | return *var; | |
983 | #endif /* INLINER_FOR_JAVA */ | |
d4e4baa9 AO |
984 | /* If FN does return an aggregate, there's no need to declare the |
985 | return variable; we're using a variable in our caller's frame. */ | |
986 | else | |
987 | return NULL_TREE; | |
988 | } | |
989 | ||
0e9e1e0a | 990 | /* Returns nonzero if a function can be inlined as a tree. */ |
4838c5ee | 991 | |
b3c3af2f SB |
992 | bool |
993 | tree_inlinable_function_p (tree fn) | |
4838c5ee | 994 | { |
b3c3af2f | 995 | return inlinable_function_p (fn); |
4838c5ee AO |
996 | } |
997 | ||
f08545a8 | 998 | static const char *inline_forbidden_reason; |
c986baf6 | 999 | |
c986baf6 | 1000 | static tree |
f08545a8 | 1001 | inline_forbidden_p_1 (tree *nodep, int *walk_subtrees ATTRIBUTE_UNUSED, |
edeb3871 | 1002 | void *fnp) |
c986baf6 | 1003 | { |
f08545a8 | 1004 | tree node = *nodep; |
edeb3871 | 1005 | tree fn = (tree) fnp; |
f08545a8 | 1006 | tree t; |
c986baf6 | 1007 | |
f08545a8 JH |
1008 | switch (TREE_CODE (node)) |
1009 | { | |
1010 | case CALL_EXPR: | |
3197c4fd AS |
1011 | /* Refuse to inline alloca call unless user explicitly forced so as |
1012 | this may change program's memory overhead drastically when the | |
1013 | function using alloca is called in loop. In GCC present in | |
1014 | SPEC2000 inlining into schedule_block cause it to require 2GB of | |
1015 | RAM instead of 256MB. */ | |
f08545a8 JH |
1016 | if (alloca_call_p (node) |
1017 | && !lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn))) | |
1018 | { | |
ddd2d57e RH |
1019 | inline_forbidden_reason |
1020 | = N_("%Jfunction '%F' can never be inlined because it uses " | |
1021 | "alloca (override using the always_inline attribute)"); | |
f08545a8 JH |
1022 | return node; |
1023 | } | |
1024 | t = get_callee_fndecl (node); | |
1025 | if (! t) | |
1026 | break; | |
84f5e1b1 | 1027 | |
84f5e1b1 | 1028 | |
f08545a8 JH |
1029 | /* We cannot inline functions that call setjmp. */ |
1030 | if (setjmp_call_p (t)) | |
1031 | { | |
ddd2d57e RH |
1032 | inline_forbidden_reason |
1033 | = N_("%Jfunction '%F' can never be inlined because it uses setjmp"); | |
f08545a8 JH |
1034 | return node; |
1035 | } | |
1036 | ||
3197c4fd AS |
1037 | if (DECL_BUILT_IN (t)) |
1038 | switch (DECL_FUNCTION_CODE (t)) | |
f08545a8 | 1039 | { |
3197c4fd AS |
1040 | /* We cannot inline functions that take a variable number of |
1041 | arguments. */ | |
1042 | case BUILT_IN_VA_START: | |
1043 | case BUILT_IN_STDARG_START: | |
1044 | case BUILT_IN_NEXT_ARG: | |
1045 | case BUILT_IN_VA_END: | |
1046 | { | |
1047 | inline_forbidden_reason | |
1048 | = N_("%Jfunction '%F' can never be inlined because it " | |
1049 | "uses variable argument lists"); | |
1050 | return node; | |
1051 | } | |
1052 | case BUILT_IN_LONGJMP: | |
1053 | { | |
1054 | /* We can't inline functions that call __builtin_longjmp at | |
1055 | all. The non-local goto machinery really requires the | |
1056 | destination be in a different function. If we allow the | |
1057 | function calling __builtin_longjmp to be inlined into the | |
1058 | function calling __builtin_setjmp, Things will Go Awry. */ | |
1059 | /* ??? Need front end help to identify "regular" non-local | |
1060 | goto. */ | |
1061 | if (DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL) | |
1062 | { | |
1063 | inline_forbidden_reason | |
1064 | = N_("%Jfunction '%F' can never be inlined because " | |
1065 | "it uses setjmp-longjmp exception handling"); | |
1066 | return node; | |
1067 | } | |
1068 | } | |
f08545a8 | 1069 | |
3197c4fd AS |
1070 | default: |
1071 | break; | |
1072 | } | |
f08545a8 JH |
1073 | break; |
1074 | ||
1075 | #ifndef INLINER_FOR_JAVA | |
1076 | case DECL_STMT: | |
1077 | /* We cannot inline functions that contain other functions. */ | |
1078 | if (TREE_CODE (TREE_OPERAND (node, 0)) == FUNCTION_DECL | |
1079 | && DECL_INITIAL (TREE_OPERAND (node, 0))) | |
1080 | { | |
ddd2d57e RH |
1081 | inline_forbidden_reason |
1082 | = N_("%Jfunction '%F' can never be inlined " | |
1083 | "because it contains a nested function"); | |
f08545a8 JH |
1084 | return node; |
1085 | } | |
1086 | break; | |
1087 | ||
1088 | case GOTO_STMT: | |
1089 | case GOTO_EXPR: | |
1090 | t = TREE_OPERAND (node, 0); | |
1091 | ||
1092 | /* We will not inline a function which uses computed goto. The | |
1093 | addresses of its local labels, which may be tucked into | |
1094 | global storage, are of course not constant across | |
1095 | instantiations, which causes unexpected behavior. */ | |
1096 | if (TREE_CODE (t) != LABEL_DECL) | |
1097 | { | |
ddd2d57e RH |
1098 | inline_forbidden_reason |
1099 | = N_("%Jfunction '%F' can never be inlined " | |
1100 | "because it contains a computed goto"); | |
f08545a8 JH |
1101 | return node; |
1102 | } | |
1103 | ||
1104 | /* We cannot inline a nested function that jumps to a nonlocal | |
1105 | label. */ | |
1106 | if (TREE_CODE (t) == LABEL_DECL && DECL_CONTEXT (t) != fn) | |
1107 | { | |
ddd2d57e RH |
1108 | inline_forbidden_reason |
1109 | = N_("%Jfunction '%F' can never be inlined " | |
1110 | "because it contains a nonlocal goto"); | |
f08545a8 JH |
1111 | return node; |
1112 | } | |
1113 | ||
1114 | break; | |
1115 | ||
1116 | case RECORD_TYPE: | |
1117 | case UNION_TYPE: | |
1118 | /* We cannot inline a function of the form | |
1119 | ||
1120 | void F (int i) { struct S { int ar[i]; } s; } | |
1121 | ||
1122 | Attempting to do so produces a catch-22. | |
1123 | If walk_tree examines the TYPE_FIELDS chain of RECORD_TYPE/ | |
1124 | UNION_TYPE nodes, then it goes into infinite recursion on a | |
1125 | structure containing a pointer to its own type. If it doesn't, | |
1126 | then the type node for S doesn't get adjusted properly when | |
1127 | F is inlined, and we abort in find_function_data. */ | |
1128 | for (t = TYPE_FIELDS (node); t; t = TREE_CHAIN (t)) | |
1129 | if (variably_modified_type_p (TREE_TYPE (t))) | |
1130 | { | |
ddd2d57e RH |
1131 | inline_forbidden_reason |
1132 | = N_("%Jfunction '%F' can never be inlined " | |
1133 | "because it uses variable sized variables"); | |
f08545a8 JH |
1134 | return node; |
1135 | } | |
1136 | #endif | |
1137 | default: | |
1138 | break; | |
1139 | } | |
1140 | ||
1141 | return NULL_TREE; | |
84f5e1b1 RH |
1142 | } |
1143 | ||
f08545a8 | 1144 | /* Return subexpression representing possible alloca call, if any. */ |
84f5e1b1 | 1145 | static tree |
f08545a8 | 1146 | inline_forbidden_p (tree fndecl) |
84f5e1b1 | 1147 | { |
070588f0 | 1148 | location_t saved_loc = input_location; |
51657442 | 1149 | tree ret = walk_tree_without_duplicates |
f08545a8 | 1150 | (&DECL_SAVED_TREE (fndecl), inline_forbidden_p_1, fndecl); |
070588f0 | 1151 | input_location = saved_loc; |
d1a74aa7 | 1152 | return ret; |
84f5e1b1 RH |
1153 | } |
1154 | ||
b3c3af2f SB |
1155 | /* Returns nonzero if FN is a function that does not have any |
1156 | fundamental inline blocking properties. */ | |
d4e4baa9 | 1157 | |
b3c3af2f SB |
1158 | static bool |
1159 | inlinable_function_p (tree fn) | |
d4e4baa9 | 1160 | { |
b3c3af2f | 1161 | bool inlinable = true; |
d4e4baa9 AO |
1162 | |
1163 | /* If we've already decided this function shouldn't be inlined, | |
1164 | there's no need to check again. */ | |
1165 | if (DECL_UNINLINABLE (fn)) | |
b3c3af2f | 1166 | return false; |
d4e4baa9 | 1167 | |
d58b7c2d MM |
1168 | /* See if there is any language-specific reason it cannot be |
1169 | inlined. (It is important that this hook be called early because | |
b3c3af2f SB |
1170 | in C++ it may result in template instantiation.) |
1171 | If the function is not inlinable for language-specific reasons, | |
1172 | it is left up to the langhook to explain why. */ | |
d58b7c2d | 1173 | inlinable = !(*lang_hooks.tree_inlining.cannot_inline_tree_fn) (&fn); |
46c5ad27 | 1174 | |
b3c3af2f SB |
1175 | /* If we don't have the function body available, we can't inline it. |
1176 | However, this should not be recorded since we also get here for | |
1177 | forward declared inline functions. Therefore, return at once. */ | |
1178 | if (!DECL_SAVED_TREE (fn)) | |
1179 | return false; | |
1180 | ||
1181 | /* If we're not inlining at all, then we cannot inline this function. */ | |
1182 | else if (!flag_inline_trees) | |
1183 | inlinable = false; | |
1184 | ||
1185 | /* Only try to inline functions if DECL_INLINE is set. This should be | |
1186 | true for all functions declared `inline', and for all other functions | |
1187 | as well with -finline-functions. | |
1188 | ||
1189 | Don't think of disregarding DECL_INLINE when flag_inline_trees == 2; | |
1190 | it's the front-end that must set DECL_INLINE in this case, because | |
1191 | dwarf2out loses if a function that does not have DECL_INLINE set is | |
1192 | inlined anyway. That is why we have both DECL_INLINE and | |
1193 | DECL_DECLARED_INLINE_P. */ | |
1194 | /* FIXME: When flag_inline_trees dies, the check for flag_unit_at_a_time | |
1195 | here should be redundant. */ | |
1196 | else if (!DECL_INLINE (fn) && !flag_unit_at_a_time) | |
1197 | inlinable = false; | |
a0c8285b | 1198 | |
0bb7378d AH |
1199 | #ifdef INLINER_FOR_JAVA |
1200 | /* Synchronized methods can't be inlined. This is a bug. */ | |
1201 | else if (METHOD_SYNCHRONIZED (fn)) | |
b3c3af2f | 1202 | inlinable = false; |
0bb7378d | 1203 | #endif /* INLINER_FOR_JAVA */ |
b3c3af2f | 1204 | |
f08545a8 | 1205 | else if (inline_forbidden_p (fn)) |
b3c3af2f SB |
1206 | { |
1207 | /* See if we should warn about uninlinable functions. Previously, | |
1208 | some of these warnings would be issued while trying to expand | |
1209 | the function inline, but that would cause multiple warnings | |
1210 | about functions that would for example call alloca. But since | |
1211 | this a property of the function, just one warning is enough. | |
1212 | As a bonus we can now give more details about the reason why a | |
1213 | function is not inlinable. | |
1214 | We only warn for functions declared `inline' by the user. */ | |
1215 | bool do_warning = (warn_inline | |
1216 | && DECL_INLINE (fn) | |
1217 | && DECL_DECLARED_INLINE_P (fn) | |
1218 | && !DECL_IN_SYSTEM_HEADER (fn)); | |
1219 | ||
2d327012 JH |
1220 | if (lookup_attribute ("always_inline", |
1221 | DECL_ATTRIBUTES (fn))) | |
1222 | sorry (inline_forbidden_reason, fn, fn); | |
1223 | else if (do_warning) | |
ddd2d57e | 1224 | warning (inline_forbidden_reason, fn, fn); |
b3c3af2f SB |
1225 | |
1226 | inlinable = false; | |
1227 | } | |
d4e4baa9 AO |
1228 | |
1229 | /* Squirrel away the result so that we don't have to check again. */ | |
b3c3af2f | 1230 | DECL_UNINLINABLE (fn) = !inlinable; |
d4e4baa9 | 1231 | |
b3c3af2f SB |
1232 | return inlinable; |
1233 | } | |
1234 | ||
d4e4baa9 AO |
1235 | /* If *TP is a CALL_EXPR, replace it with its inline expansion. */ |
1236 | ||
1237 | static tree | |
46c5ad27 | 1238 | expand_call_inline (tree *tp, int *walk_subtrees, void *data) |
d4e4baa9 AO |
1239 | { |
1240 | inline_data *id; | |
1241 | tree t; | |
1242 | tree expr; | |
e2405951 | 1243 | tree stmt; |
d436bff8 | 1244 | #ifndef INLINER_FOR_JAVA |
d4e4baa9 | 1245 | tree chain; |
d4e4baa9 AO |
1246 | tree scope_stmt; |
1247 | tree use_stmt; | |
d436bff8 AH |
1248 | #else /* INLINER_FOR_JAVA */ |
1249 | tree retvar; | |
1250 | #endif /* INLINER_FOR_JAVA */ | |
1251 | tree fn; | |
d4e4baa9 AO |
1252 | tree arg_inits; |
1253 | tree *inlined_body; | |
1254 | splay_tree st; | |
4977bab6 ZW |
1255 | tree args; |
1256 | tree return_slot_addr; | |
dc0bfe6a | 1257 | const char *reason; |
d4e4baa9 AO |
1258 | |
1259 | /* See what we've got. */ | |
1260 | id = (inline_data *) data; | |
1261 | t = *tp; | |
1262 | ||
1263 | /* Recurse, but letting recursive invocations know that we are | |
1264 | inside the body of a TARGET_EXPR. */ | |
1265 | if (TREE_CODE (*tp) == TARGET_EXPR) | |
1266 | { | |
d436bff8 | 1267 | #ifndef INLINER_FOR_JAVA |
d4e4baa9 AO |
1268 | int i, len = first_rtl_op (TARGET_EXPR); |
1269 | ||
1270 | /* We're walking our own subtrees. */ | |
1271 | *walk_subtrees = 0; | |
1272 | ||
d4e4baa9 AO |
1273 | /* Actually walk over them. This loop is the body of |
1274 | walk_trees, omitting the case where the TARGET_EXPR | |
1275 | itself is handled. */ | |
1276 | for (i = 0; i < len; ++i) | |
1277 | { | |
1278 | if (i == 2) | |
1279 | ++id->in_target_cleanup_p; | |
1280 | walk_tree (&TREE_OPERAND (*tp, i), expand_call_inline, data, | |
1281 | id->tree_pruner); | |
1282 | if (i == 2) | |
1283 | --id->in_target_cleanup_p; | |
1284 | } | |
1285 | ||
d4e4baa9 | 1286 | return NULL_TREE; |
d436bff8 AH |
1287 | #else /* INLINER_FOR_JAVA */ |
1288 | abort (); | |
1289 | #endif /* INLINER_FOR_JAVA */ | |
d4e4baa9 | 1290 | } |
a833faa5 MM |
1291 | else if (TREE_CODE (t) == EXPR_WITH_FILE_LOCATION) |
1292 | { | |
1293 | /* We're walking the subtree directly. */ | |
1294 | *walk_subtrees = 0; | |
1295 | /* Update the source position. */ | |
1296 | push_srcloc (EXPR_WFL_FILENAME (t), EXPR_WFL_LINENO (t)); | |
46c5ad27 | 1297 | walk_tree (&EXPR_WFL_NODE (t), expand_call_inline, data, |
a833faa5 MM |
1298 | id->tree_pruner); |
1299 | /* Restore the original source position. */ | |
1300 | pop_srcloc (); | |
1301 | ||
1302 | return NULL_TREE; | |
1303 | } | |
d4e4baa9 AO |
1304 | |
1305 | if (TYPE_P (t)) | |
1306 | /* Because types were not copied in copy_body, CALL_EXPRs beneath | |
1307 | them should not be expanded. This can happen if the type is a | |
1308 | dynamic array type, for example. */ | |
1309 | *walk_subtrees = 0; | |
1310 | ||
1311 | /* From here on, we're only interested in CALL_EXPRs. */ | |
1312 | if (TREE_CODE (t) != CALL_EXPR) | |
1313 | return NULL_TREE; | |
1314 | ||
1315 | /* First, see if we can figure out what function is being called. | |
1316 | If we cannot, then there is no hope of inlining the function. */ | |
1317 | fn = get_callee_fndecl (t); | |
1318 | if (!fn) | |
1319 | return NULL_TREE; | |
1320 | ||
b58b1157 | 1321 | /* Turn forward declarations into real ones. */ |
d4d1ebc1 | 1322 | fn = cgraph_node (fn)->decl; |
b58b1157 | 1323 | |
a1a0fd4e AO |
1324 | /* If fn is a declaration of a function in a nested scope that was |
1325 | globally declared inline, we don't set its DECL_INITIAL. | |
1326 | However, we can't blindly follow DECL_ABSTRACT_ORIGIN because the | |
1327 | C++ front-end uses it for cdtors to refer to their internal | |
1328 | declarations, that are not real functions. Fortunately those | |
1329 | don't have trees to be saved, so we can tell by checking their | |
1330 | DECL_SAVED_TREE. */ | |
1331 | if (! DECL_INITIAL (fn) | |
1332 | && DECL_ABSTRACT_ORIGIN (fn) | |
1333 | && DECL_SAVED_TREE (DECL_ABSTRACT_ORIGIN (fn))) | |
1334 | fn = DECL_ABSTRACT_ORIGIN (fn); | |
1335 | ||
d4e4baa9 AO |
1336 | /* Don't try to inline functions that are not well-suited to |
1337 | inlining. */ | |
dc0bfe6a | 1338 | if (!cgraph_inline_p (id->current_decl, fn, &reason)) |
a833faa5 | 1339 | { |
2d327012 JH |
1340 | if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn))) |
1341 | { | |
1342 | sorry ("%Jinlining failed in call to '%F': %s", fn, fn, reason); | |
1343 | sorry ("called from here"); | |
1344 | } | |
1345 | else if (warn_inline && DECL_DECLARED_INLINE_P (fn) | |
1346 | && !DECL_IN_SYSTEM_HEADER (fn) | |
1347 | && strlen (reason)) | |
a833faa5 | 1348 | { |
dc0bfe6a | 1349 | warning ("%Jinlining failed in call to '%F': %s", fn, fn, reason); |
a833faa5 MM |
1350 | warning ("called from here"); |
1351 | } | |
1352 | return NULL_TREE; | |
1353 | } | |
d4e4baa9 | 1354 | |
742a37d5 JM |
1355 | if (! (*lang_hooks.tree_inlining.start_inlining) (fn)) |
1356 | return NULL_TREE; | |
1357 | ||
d4e4baa9 AO |
1358 | /* Set the current filename and line number to the function we are |
1359 | inlining so that when we create new _STMT nodes here they get | |
1360 | line numbers corresponding to the function we are calling. We | |
1361 | wrap the whole inlined body in an EXPR_WITH_FILE_AND_LINE as well | |
1362 | because individual statements don't record the filename. */ | |
f31686a3 | 1363 | push_srcloc (DECL_SOURCE_FILE (fn), DECL_SOURCE_LINE (fn)); |
d4e4baa9 | 1364 | |
d436bff8 | 1365 | #ifndef INLINER_FOR_JAVA |
d4e4baa9 AO |
1366 | /* Build a statement-expression containing code to initialize the |
1367 | arguments, the actual inline expansion of the body, and a label | |
1368 | for the return statements within the function to jump to. The | |
1369 | type of the statement expression is the return type of the | |
1370 | function call. */ | |
e2405951 | 1371 | expr = build1 (STMT_EXPR, TREE_TYPE (TREE_TYPE (fn)), make_node (COMPOUND_STMT)); |
b2123dc0 MM |
1372 | /* There is no scope associated with the statement-expression. */ |
1373 | STMT_EXPR_NO_SCOPE (expr) = 1; | |
72954a4f JM |
1374 | if (lookup_attribute ("warn_unused_result", |
1375 | TYPE_ATTRIBUTES (TREE_TYPE (fn)))) | |
1376 | STMT_EXPR_WARN_UNUSED_RESULT (expr) = 1; | |
e2405951 | 1377 | stmt = STMT_EXPR_STMT (expr); |
d436bff8 AH |
1378 | #else /* INLINER_FOR_JAVA */ |
1379 | /* Build a block containing code to initialize the arguments, the | |
1380 | actual inline expansion of the body, and a label for the return | |
1381 | statements within the function to jump to. The type of the | |
1382 | statement expression is the return type of the function call. */ | |
1383 | stmt = NULL; | |
4221057e | 1384 | expr = build (BLOCK, TREE_TYPE (TREE_TYPE (fn))); |
d436bff8 AH |
1385 | #endif /* INLINER_FOR_JAVA */ |
1386 | ||
d4e4baa9 AO |
1387 | /* Local declarations will be replaced by their equivalents in this |
1388 | map. */ | |
1389 | st = id->decl_map; | |
1390 | id->decl_map = splay_tree_new (splay_tree_compare_pointers, | |
1391 | NULL, NULL); | |
1392 | ||
1393 | /* Initialize the parameters. */ | |
4977bab6 ZW |
1394 | args = TREE_OPERAND (t, 1); |
1395 | return_slot_addr = NULL_TREE; | |
1396 | if (CALL_EXPR_HAS_RETURN_SLOT_ADDR (t)) | |
1397 | { | |
1398 | return_slot_addr = TREE_VALUE (args); | |
1399 | args = TREE_CHAIN (args); | |
1400 | } | |
1401 | ||
d436bff8 | 1402 | #ifndef INLINER_FOR_JAVA |
4977bab6 | 1403 | arg_inits = initialize_inlined_parameters (id, args, fn); |
d4e4baa9 AO |
1404 | /* Expand any inlined calls in the initializers. Do this before we |
1405 | push FN on the stack of functions we are inlining; we want to | |
1406 | inline calls to FN that appear in the initializers for the | |
1407 | parameters. */ | |
1408 | expand_calls_inline (&arg_inits, id); | |
1409 | /* And add them to the tree. */ | |
e2405951 | 1410 | COMPOUND_BODY (stmt) = chainon (COMPOUND_BODY (stmt), arg_inits); |
d436bff8 | 1411 | #else /* INLINER_FOR_JAVA */ |
4977bab6 | 1412 | arg_inits = initialize_inlined_parameters (id, args, fn, expr); |
d436bff8 AH |
1413 | if (arg_inits) |
1414 | { | |
1415 | /* Expand any inlined calls in the initializers. Do this before we | |
1416 | push FN on the stack of functions we are inlining; we want to | |
1417 | inline calls to FN that appear in the initializers for the | |
1418 | parameters. */ | |
1419 | expand_calls_inline (&arg_inits, id); | |
50aadcbc | 1420 | |
d436bff8 | 1421 | /* And add them to the tree. */ |
50aadcbc AJ |
1422 | BLOCK_EXPR_BODY (expr) = add_stmt_to_compound (BLOCK_EXPR_BODY (expr), |
1423 | TREE_TYPE (arg_inits), | |
d436bff8 AH |
1424 | arg_inits); |
1425 | } | |
1426 | #endif /* INLINER_FOR_JAVA */ | |
d4e4baa9 AO |
1427 | |
1428 | /* Record the function we are about to inline so that we can avoid | |
1429 | recursing into it. */ | |
1430 | VARRAY_PUSH_TREE (id->fns, fn); | |
1431 | ||
1432 | /* Record the function we are about to inline if optimize_function | |
1433 | has not been called on it yet and we don't have it in the list. */ | |
1434 | if (! DECL_INLINED_FNS (fn)) | |
1435 | { | |
1436 | int i; | |
1437 | ||
1438 | for (i = VARRAY_ACTIVE_SIZE (id->inlined_fns) - 1; i >= 0; i--) | |
1439 | if (VARRAY_TREE (id->inlined_fns, i) == fn) | |
1440 | break; | |
1441 | if (i < 0) | |
1442 | VARRAY_PUSH_TREE (id->inlined_fns, fn); | |
1443 | } | |
1444 | ||
1445 | /* Return statements in the function body will be replaced by jumps | |
1446 | to the RET_LABEL. */ | |
1447 | id->ret_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); | |
1448 | DECL_CONTEXT (id->ret_label) = VARRAY_TREE (id->fns, 0); | |
1449 | ||
23700f65 AO |
1450 | if (! DECL_INITIAL (fn) |
1451 | || TREE_CODE (DECL_INITIAL (fn)) != BLOCK) | |
1452 | abort (); | |
1453 | ||
d436bff8 | 1454 | #ifndef INLINER_FOR_JAVA |
d4e4baa9 AO |
1455 | /* Create a block to put the parameters in. We have to do this |
1456 | after the parameters have been remapped because remapping | |
1457 | parameters is different from remapping ordinary variables. */ | |
1458 | scope_stmt = build_stmt (SCOPE_STMT, DECL_INITIAL (fn)); | |
1459 | SCOPE_BEGIN_P (scope_stmt) = 1; | |
1460 | SCOPE_NO_CLEANUPS_P (scope_stmt) = 1; | |
1461 | remap_block (scope_stmt, DECL_ARGUMENTS (fn), id); | |
e2405951 DB |
1462 | TREE_CHAIN (scope_stmt) = COMPOUND_BODY (stmt); |
1463 | COMPOUND_BODY (stmt) = scope_stmt; | |
d4e4baa9 AO |
1464 | |
1465 | /* Tell the debugging backends that this block represents the | |
1466 | outermost scope of the inlined function. */ | |
1467 | if (SCOPE_STMT_BLOCK (scope_stmt)) | |
1468 | BLOCK_ABSTRACT_ORIGIN (SCOPE_STMT_BLOCK (scope_stmt)) = DECL_ORIGIN (fn); | |
1469 | ||
1470 | /* Declare the return variable for the function. */ | |
e2405951 DB |
1471 | COMPOUND_BODY (stmt) |
1472 | = chainon (COMPOUND_BODY (stmt), | |
4977bab6 | 1473 | declare_return_variable (id, return_slot_addr, &use_stmt)); |
d436bff8 AH |
1474 | #else /* INLINER_FOR_JAVA */ |
1475 | { | |
1476 | /* Declare the return variable for the function. */ | |
4977bab6 | 1477 | tree decl = declare_return_variable (id, return_slot_addr, &retvar); |
d436bff8 AH |
1478 | if (retvar) |
1479 | { | |
1480 | tree *next = &BLOCK_VARS (expr); | |
1481 | while (*next) | |
50aadcbc | 1482 | next = &TREE_CHAIN (*next); |
d436bff8 AH |
1483 | *next = decl; |
1484 | } | |
1485 | } | |
1486 | #endif /* INLINER_FOR_JAVA */ | |
d4e4baa9 AO |
1487 | |
1488 | /* After we've initialized the parameters, we insert the body of the | |
1489 | function itself. */ | |
d436bff8 | 1490 | #ifndef INLINER_FOR_JAVA |
e2405951 | 1491 | inlined_body = &COMPOUND_BODY (stmt); |
d4e4baa9 AO |
1492 | while (*inlined_body) |
1493 | inlined_body = &TREE_CHAIN (*inlined_body); | |
1494 | *inlined_body = copy_body (id); | |
d436bff8 AH |
1495 | #else /* INLINER_FOR_JAVA */ |
1496 | { | |
3eb429b2 AH |
1497 | tree new_body; |
1498 | java_inlining_map_static_initializers (fn, id->decl_map); | |
1499 | new_body = copy_body (id); | |
d436bff8 AH |
1500 | TREE_TYPE (new_body) = TREE_TYPE (TREE_TYPE (fn)); |
1501 | BLOCK_EXPR_BODY (expr) | |
50aadcbc | 1502 | = add_stmt_to_compound (BLOCK_EXPR_BODY (expr), |
d436bff8 AH |
1503 | TREE_TYPE (new_body), new_body); |
1504 | inlined_body = &BLOCK_EXPR_BODY (expr); | |
1505 | } | |
1506 | #endif /* INLINER_FOR_JAVA */ | |
d4e4baa9 | 1507 | |
d4e4baa9 | 1508 | /* After the body of the function comes the RET_LABEL. This must come |
14b493d6 | 1509 | before we evaluate the returned value below, because that evaluation |
d4e4baa9 | 1510 | may cause RTL to be generated. */ |
d436bff8 | 1511 | #ifndef INLINER_FOR_JAVA |
e2405951 DB |
1512 | COMPOUND_BODY (stmt) |
1513 | = chainon (COMPOUND_BODY (stmt), | |
d4e4baa9 | 1514 | build_stmt (LABEL_STMT, id->ret_label)); |
d436bff8 AH |
1515 | #else /* INLINER_FOR_JAVA */ |
1516 | { | |
1517 | tree label = build1 (LABEL_EXPR, void_type_node, id->ret_label); | |
1518 | BLOCK_EXPR_BODY (expr) | |
1519 | = add_stmt_to_compound (BLOCK_EXPR_BODY (expr), void_type_node, label); | |
1520 | TREE_SIDE_EFFECTS (label) = TREE_SIDE_EFFECTS (t); | |
1521 | } | |
1522 | #endif /* INLINER_FOR_JAVA */ | |
d4e4baa9 AO |
1523 | |
1524 | /* Finally, mention the returned value so that the value of the | |
1525 | statement-expression is the returned value of the function. */ | |
d436bff8 | 1526 | #ifndef INLINER_FOR_JAVA |
e2405951 | 1527 | COMPOUND_BODY (stmt) = chainon (COMPOUND_BODY (stmt), use_stmt); |
50aadcbc | 1528 | |
e2405951 DB |
1529 | /* Close the block for the parameters. */ |
1530 | scope_stmt = build_stmt (SCOPE_STMT, DECL_INITIAL (fn)); | |
1531 | SCOPE_NO_CLEANUPS_P (scope_stmt) = 1; | |
1532 | remap_block (scope_stmt, NULL_TREE, id); | |
1533 | COMPOUND_BODY (stmt) | |
1534 | = chainon (COMPOUND_BODY (stmt), scope_stmt); | |
d436bff8 AH |
1535 | #else /* INLINER_FOR_JAVA */ |
1536 | if (retvar) | |
3eb429b2 AH |
1537 | { |
1538 | /* Mention the retvar. If the return type of the function was | |
1539 | promoted, convert it back to the expected type. */ | |
1540 | if (TREE_TYPE (TREE_TYPE (fn)) != TREE_TYPE (retvar)) | |
1541 | retvar = build1 (NOP_EXPR, TREE_TYPE (TREE_TYPE (fn)), retvar); | |
50aadcbc AJ |
1542 | BLOCK_EXPR_BODY (expr) |
1543 | = add_stmt_to_compound (BLOCK_EXPR_BODY (expr), | |
3eb429b2 AH |
1544 | TREE_TYPE (retvar), retvar); |
1545 | } | |
50aadcbc | 1546 | |
3eb429b2 | 1547 | java_inlining_merge_static_initializers (fn, id->decl_map); |
d436bff8 | 1548 | #endif /* INLINER_FOR_JAVA */ |
d4e4baa9 AO |
1549 | |
1550 | /* Clean up. */ | |
1551 | splay_tree_delete (id->decl_map); | |
1552 | id->decl_map = st; | |
1553 | ||
1554 | /* The new expression has side-effects if the old one did. */ | |
1555 | TREE_SIDE_EFFECTS (expr) = TREE_SIDE_EFFECTS (t); | |
1556 | ||
1557 | /* Replace the call by the inlined body. Wrap it in an | |
1558 | EXPR_WITH_FILE_LOCATION so that we'll get debugging line notes | |
1559 | pointing to the right place. */ | |
d436bff8 | 1560 | #ifndef INLINER_FOR_JAVA |
d4e4baa9 | 1561 | chain = TREE_CHAIN (*tp); |
36f04556 | 1562 | #endif /* INLINER_FOR_JAVA */ |
f31686a3 | 1563 | *tp = build_expr_wfl (expr, DECL_SOURCE_FILE (fn), DECL_SOURCE_LINE (fn), |
d4e4baa9 AO |
1564 | /*col=*/0); |
1565 | EXPR_WFL_EMIT_LINE_NOTE (*tp) = 1; | |
d436bff8 | 1566 | #ifndef INLINER_FOR_JAVA |
d4e4baa9 | 1567 | TREE_CHAIN (*tp) = chain; |
d436bff8 | 1568 | #endif /* not INLINER_FOR_JAVA */ |
d4e4baa9 AO |
1569 | pop_srcloc (); |
1570 | ||
1571 | /* If the value of the new expression is ignored, that's OK. We | |
1572 | don't warn about this for CALL_EXPRs, so we shouldn't warn about | |
1573 | the equivalent inlined version either. */ | |
1574 | TREE_USED (*tp) = 1; | |
1575 | ||
e72fcfe8 | 1576 | /* Update callgraph if needed. */ |
d4d1ebc1 | 1577 | if (id->decl) |
e72fcfe8 JH |
1578 | { |
1579 | cgraph_remove_call (id->decl, fn); | |
1580 | cgraph_create_edges (id->decl, *inlined_body); | |
1581 | } | |
1582 | ||
d4e4baa9 | 1583 | /* Recurse into the body of the just inlined function. */ |
b58b1157 JH |
1584 | { |
1585 | tree old_decl = id->current_decl; | |
1586 | id->current_decl = fn; | |
1587 | expand_calls_inline (inlined_body, id); | |
1588 | id->current_decl = old_decl; | |
1589 | } | |
d4e4baa9 AO |
1590 | VARRAY_POP (id->fns); |
1591 | ||
d4e4baa9 AO |
1592 | /* Don't walk into subtrees. We've already handled them above. */ |
1593 | *walk_subtrees = 0; | |
1594 | ||
742a37d5 JM |
1595 | (*lang_hooks.tree_inlining.end_inlining) (fn); |
1596 | ||
d4e4baa9 AO |
1597 | /* Keep iterating. */ |
1598 | return NULL_TREE; | |
1599 | } | |
d4e4baa9 AO |
1600 | /* Walk over the entire tree *TP, replacing CALL_EXPRs with inline |
1601 | expansions as appropriate. */ | |
1602 | ||
1603 | static void | |
46c5ad27 | 1604 | expand_calls_inline (tree *tp, inline_data *id) |
d4e4baa9 AO |
1605 | { |
1606 | /* Search through *TP, replacing all calls to inline functions by | |
1607 | appropriate equivalents. Use walk_tree in no-duplicates mode | |
1608 | to avoid exponential time complexity. (We can't just use | |
1609 | walk_tree_without_duplicates, because of the special TARGET_EXPR | |
1610 | handling in expand_calls. The hash table is set up in | |
1611 | optimize_function. */ | |
1612 | walk_tree (tp, expand_call_inline, id, id->tree_pruner); | |
1613 | } | |
1614 | ||
1615 | /* Expand calls to inline functions in the body of FN. */ | |
1616 | ||
1617 | void | |
46c5ad27 | 1618 | optimize_inline_calls (tree fn) |
d4e4baa9 AO |
1619 | { |
1620 | inline_data id; | |
1621 | tree prev_fn; | |
d92b4486 | 1622 | |
c5b6f18e MM |
1623 | /* There is no point in performing inlining if errors have already |
1624 | occurred -- and we might crash if we try to inline invalid | |
1625 | code. */ | |
1626 | if (errorcount || sorrycount) | |
1627 | return; | |
1628 | ||
d4e4baa9 AO |
1629 | /* Clear out ID. */ |
1630 | memset (&id, 0, sizeof (id)); | |
1631 | ||
e72fcfe8 | 1632 | id.decl = fn; |
b58b1157 | 1633 | id.current_decl = fn; |
d4e4baa9 AO |
1634 | /* Don't allow recursion into FN. */ |
1635 | VARRAY_TREE_INIT (id.fns, 32, "fns"); | |
1636 | VARRAY_PUSH_TREE (id.fns, fn); | |
1637 | /* Or any functions that aren't finished yet. */ | |
1638 | prev_fn = NULL_TREE; | |
1639 | if (current_function_decl) | |
1640 | { | |
1641 | VARRAY_PUSH_TREE (id.fns, current_function_decl); | |
1642 | prev_fn = current_function_decl; | |
1643 | } | |
1644 | ||
69dcadff AO |
1645 | prev_fn = ((*lang_hooks.tree_inlining.add_pending_fn_decls) |
1646 | (&id.fns, prev_fn)); | |
d92b4486 | 1647 | |
d4e4baa9 AO |
1648 | /* Create the list of functions this call will inline. */ |
1649 | VARRAY_TREE_INIT (id.inlined_fns, 32, "inlined_fns"); | |
1650 | ||
1651 | /* Keep track of the low-water mark, i.e., the point where the first | |
1652 | real inlining is represented in ID.FNS. */ | |
1653 | id.first_inlined_fn = VARRAY_ACTIVE_SIZE (id.fns); | |
1654 | ||
1655 | /* Replace all calls to inline functions with the bodies of those | |
1656 | functions. */ | |
1657 | id.tree_pruner = htab_create (37, htab_hash_pointer, | |
1658 | htab_eq_pointer, NULL); | |
1659 | expand_calls_inline (&DECL_SAVED_TREE (fn), &id); | |
1660 | ||
1661 | /* Clean up. */ | |
1662 | htab_delete (id.tree_pruner); | |
d4e4baa9 AO |
1663 | if (DECL_LANG_SPECIFIC (fn)) |
1664 | { | |
1665 | tree ifn = make_tree_vec (VARRAY_ACTIVE_SIZE (id.inlined_fns)); | |
d92b4486 | 1666 | |
fa7b533b ZW |
1667 | if (VARRAY_ACTIVE_SIZE (id.inlined_fns)) |
1668 | memcpy (&TREE_VEC_ELT (ifn, 0), &VARRAY_TREE (id.inlined_fns, 0), | |
1669 | VARRAY_ACTIVE_SIZE (id.inlined_fns) * sizeof (tree)); | |
d4e4baa9 AO |
1670 | DECL_INLINED_FNS (fn) = ifn; |
1671 | } | |
d4e4baa9 AO |
1672 | } |
1673 | ||
1674 | /* FN is a function that has a complete body, and CLONE is a function | |
1675 | whose body is to be set to a copy of FN, mapping argument | |
1676 | declarations according to the ARG_MAP splay_tree. */ | |
1677 | ||
1678 | void | |
46c5ad27 | 1679 | clone_body (tree clone, tree fn, void *arg_map) |
d4e4baa9 AO |
1680 | { |
1681 | inline_data id; | |
1682 | ||
1683 | /* Clone the body, as if we were making an inline call. But, remap | |
1684 | the parameters in the callee to the parameters of caller. If | |
1685 | there's an in-charge parameter, map it to an appropriate | |
1686 | constant. */ | |
1687 | memset (&id, 0, sizeof (id)); | |
1688 | VARRAY_TREE_INIT (id.fns, 2, "fns"); | |
1689 | VARRAY_PUSH_TREE (id.fns, clone); | |
1690 | VARRAY_PUSH_TREE (id.fns, fn); | |
1691 | id.decl_map = (splay_tree)arg_map; | |
1692 | ||
1693 | /* Cloning is treated slightly differently from inlining. Set | |
1694 | CLONING_P so that it's clear which operation we're performing. */ | |
1695 | id.cloning_p = true; | |
1696 | ||
1697 | /* Actually copy the body. */ | |
1698 | TREE_CHAIN (DECL_SAVED_TREE (clone)) = copy_body (&id); | |
d4e4baa9 AO |
1699 | } |
1700 | ||
1701 | /* Apply FUNC to all the sub-trees of TP in a pre-order traversal. | |
1702 | FUNC is called with the DATA and the address of each sub-tree. If | |
1703 | FUNC returns a non-NULL value, the traversal is aborted, and the | |
1704 | value returned by FUNC is returned. If HTAB is non-NULL it is used | |
1705 | to record the nodes visited, and to avoid visiting a node more than | |
1706 | once. */ | |
1707 | ||
d92b4486 | 1708 | tree |
46c5ad27 | 1709 | walk_tree (tree *tp, walk_tree_fn func, void *data, void *htab_) |
d4e4baa9 AO |
1710 | { |
1711 | htab_t htab = (htab_t) htab_; | |
1712 | enum tree_code code; | |
1713 | int walk_subtrees; | |
1714 | tree result; | |
d92b4486 | 1715 | |
d4e4baa9 AO |
1716 | #define WALK_SUBTREE(NODE) \ |
1717 | do \ | |
1718 | { \ | |
1719 | result = walk_tree (&(NODE), func, data, htab); \ | |
1720 | if (result) \ | |
1721 | return result; \ | |
1722 | } \ | |
1723 | while (0) | |
1724 | ||
6c624f7f AO |
1725 | #define WALK_SUBTREE_TAIL(NODE) \ |
1726 | do \ | |
1727 | { \ | |
1728 | tp = & (NODE); \ | |
1729 | goto tail_recurse; \ | |
1730 | } \ | |
1731 | while (0) | |
1732 | ||
1733 | tail_recurse: | |
d4e4baa9 AO |
1734 | /* Skip empty subtrees. */ |
1735 | if (!*tp) | |
1736 | return NULL_TREE; | |
1737 | ||
1738 | if (htab) | |
1739 | { | |
1740 | void **slot; | |
d92b4486 | 1741 | |
d4e4baa9 | 1742 | /* Don't walk the same tree twice, if the user has requested |
2ba84f36 | 1743 | that we avoid doing so. */ |
d4e4baa9 | 1744 | slot = htab_find_slot (htab, *tp, INSERT); |
c35c7e52 RH |
1745 | if (*slot) |
1746 | return NULL_TREE; | |
d4e4baa9 AO |
1747 | *slot = *tp; |
1748 | } | |
1749 | ||
1750 | /* Call the function. */ | |
1751 | walk_subtrees = 1; | |
1752 | result = (*func) (tp, &walk_subtrees, data); | |
1753 | ||
1754 | /* If we found something, return it. */ | |
1755 | if (result) | |
1756 | return result; | |
1757 | ||
1758 | code = TREE_CODE (*tp); | |
1759 | ||
d436bff8 | 1760 | #ifndef INLINER_FOR_JAVA |
d4e4baa9 AO |
1761 | /* Even if we didn't, FUNC may have decided that there was nothing |
1762 | interesting below this point in the tree. */ | |
1763 | if (!walk_subtrees) | |
1764 | { | |
009ed910 | 1765 | if (STATEMENT_CODE_P (code) || code == TREE_LIST |
69dcadff | 1766 | || (*lang_hooks.tree_inlining.tree_chain_matters_p) (*tp)) |
d4e4baa9 | 1767 | /* But we still need to check our siblings. */ |
6c624f7f | 1768 | WALK_SUBTREE_TAIL (TREE_CHAIN (*tp)); |
d4e4baa9 AO |
1769 | else |
1770 | return NULL_TREE; | |
1771 | } | |
1772 | ||
1773 | /* Handle common cases up front. */ | |
68ad9159 | 1774 | if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))) |
d436bff8 AH |
1775 | #else /* INLINER_FOR_JAVA */ |
1776 | if (code != EXIT_BLOCK_EXPR | |
1777 | && code != SAVE_EXPR | |
68ad9159 | 1778 | && IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))) |
d436bff8 | 1779 | #endif /* INLINER_FOR_JAVA */ |
d4e4baa9 AO |
1780 | { |
1781 | int i, len; | |
1782 | ||
d436bff8 | 1783 | #ifndef INLINER_FOR_JAVA |
d4e4baa9 AO |
1784 | /* Set lineno here so we get the right instantiation context |
1785 | if we call instantiate_decl from inlinable_function_p. */ | |
009ed910 | 1786 | if (STATEMENT_CODE_P (code) && !STMT_LINENO_FOR_FN_P (*tp)) |
d479d37f | 1787 | input_line = STMT_LINENO (*tp); |
d436bff8 | 1788 | #endif /* not INLINER_FOR_JAVA */ |
d4e4baa9 AO |
1789 | |
1790 | /* Walk over all the sub-trees of this operand. */ | |
1791 | len = first_rtl_op (code); | |
1792 | /* TARGET_EXPRs are peculiar: operands 1 and 3 can be the same. | |
1793 | But, we only want to walk once. */ | |
1794 | if (code == TARGET_EXPR | |
1795 | && TREE_OPERAND (*tp, 3) == TREE_OPERAND (*tp, 1)) | |
1796 | --len; | |
1797 | /* Go through the subtrees. We need to do this in forward order so | |
1798 | that the scope of a FOR_EXPR is handled properly. */ | |
1799 | for (i = 0; i < len; ++i) | |
1800 | WALK_SUBTREE (TREE_OPERAND (*tp, i)); | |
1801 | ||
d436bff8 | 1802 | #ifndef INLINER_FOR_JAVA |
d4e4baa9 AO |
1803 | /* For statements, we also walk the chain so that we cover the |
1804 | entire statement tree. */ | |
009ed910 | 1805 | if (STATEMENT_CODE_P (code)) |
d4e4baa9 | 1806 | { |
d92b4486 KH |
1807 | if (code == DECL_STMT |
1808 | && DECL_STMT_DECL (*tp) | |
d4e4baa9 AO |
1809 | && DECL_P (DECL_STMT_DECL (*tp))) |
1810 | { | |
1811 | /* Walk the DECL_INITIAL and DECL_SIZE. We don't want to walk | |
1812 | into declarations that are just mentioned, rather than | |
1813 | declared; they don't really belong to this part of the tree. | |
1814 | And, we can see cycles: the initializer for a declaration can | |
1815 | refer to the declaration itself. */ | |
1816 | WALK_SUBTREE (DECL_INITIAL (DECL_STMT_DECL (*tp))); | |
1817 | WALK_SUBTREE (DECL_SIZE (DECL_STMT_DECL (*tp))); | |
1818 | WALK_SUBTREE (DECL_SIZE_UNIT (DECL_STMT_DECL (*tp))); | |
3c2a7a6a | 1819 | WALK_SUBTREE (TREE_TYPE (*tp)); |
d4e4baa9 AO |
1820 | } |
1821 | ||
1822 | /* This can be tail-recursion optimized if we write it this way. */ | |
6c624f7f | 1823 | WALK_SUBTREE_TAIL (TREE_CHAIN (*tp)); |
d4e4baa9 AO |
1824 | } |
1825 | ||
d436bff8 | 1826 | #endif /* not INLINER_FOR_JAVA */ |
d4e4baa9 AO |
1827 | /* We didn't find what we were looking for. */ |
1828 | return NULL_TREE; | |
1829 | } | |
1830 | else if (TREE_CODE_CLASS (code) == 'd') | |
1831 | { | |
6c624f7f | 1832 | WALK_SUBTREE_TAIL (TREE_TYPE (*tp)); |
d4e4baa9 | 1833 | } |
f3763a44 ZW |
1834 | else if (TREE_CODE_CLASS (code) == 't') |
1835 | { | |
1836 | WALK_SUBTREE (TYPE_SIZE (*tp)); | |
1837 | WALK_SUBTREE (TYPE_SIZE_UNIT (*tp)); | |
1838 | /* Also examine various special fields, below. */ | |
1839 | } | |
d4e4baa9 | 1840 | |
69dcadff AO |
1841 | result = (*lang_hooks.tree_inlining.walk_subtrees) (tp, &walk_subtrees, func, |
1842 | data, htab); | |
d4e4baa9 AO |
1843 | if (result || ! walk_subtrees) |
1844 | return result; | |
1845 | ||
1846 | /* Not one of the easy cases. We must explicitly go through the | |
1847 | children. */ | |
1848 | switch (code) | |
1849 | { | |
1850 | case ERROR_MARK: | |
1851 | case IDENTIFIER_NODE: | |
1852 | case INTEGER_CST: | |
1853 | case REAL_CST: | |
69ef87e2 | 1854 | case VECTOR_CST: |
d4e4baa9 AO |
1855 | case STRING_CST: |
1856 | case REAL_TYPE: | |
1857 | case COMPLEX_TYPE: | |
1858 | case VECTOR_TYPE: | |
1859 | case VOID_TYPE: | |
1860 | case BOOLEAN_TYPE: | |
1861 | case UNION_TYPE: | |
1862 | case ENUMERAL_TYPE: | |
1863 | case BLOCK: | |
1864 | case RECORD_TYPE: | |
cf0150b9 | 1865 | case CHAR_TYPE: |
415294f0 | 1866 | case PLACEHOLDER_EXPR: |
2067c116 | 1867 | /* None of these have subtrees other than those already walked |
d4e4baa9 AO |
1868 | above. */ |
1869 | break; | |
1870 | ||
1871 | case POINTER_TYPE: | |
1872 | case REFERENCE_TYPE: | |
6c624f7f | 1873 | WALK_SUBTREE_TAIL (TREE_TYPE (*tp)); |
d4e4baa9 AO |
1874 | break; |
1875 | ||
1876 | case TREE_LIST: | |
1877 | WALK_SUBTREE (TREE_VALUE (*tp)); | |
6c624f7f | 1878 | WALK_SUBTREE_TAIL (TREE_CHAIN (*tp)); |
d4e4baa9 AO |
1879 | break; |
1880 | ||
1881 | case TREE_VEC: | |
1882 | { | |
1883 | int len = TREE_VEC_LENGTH (*tp); | |
6c624f7f AO |
1884 | |
1885 | if (len == 0) | |
1886 | break; | |
1887 | ||
1888 | /* Walk all elements but the first. */ | |
1889 | while (--len) | |
d4e4baa9 | 1890 | WALK_SUBTREE (TREE_VEC_ELT (*tp, len)); |
6c624f7f AO |
1891 | |
1892 | /* Now walk the first one as a tail call. */ | |
1893 | WALK_SUBTREE_TAIL (TREE_VEC_ELT (*tp, 0)); | |
d4e4baa9 | 1894 | } |
d4e4baa9 AO |
1895 | |
1896 | case COMPLEX_CST: | |
1897 | WALK_SUBTREE (TREE_REALPART (*tp)); | |
6c624f7f | 1898 | WALK_SUBTREE_TAIL (TREE_IMAGPART (*tp)); |
d4e4baa9 AO |
1899 | |
1900 | case CONSTRUCTOR: | |
6c624f7f | 1901 | WALK_SUBTREE_TAIL (CONSTRUCTOR_ELTS (*tp)); |
d4e4baa9 AO |
1902 | |
1903 | case METHOD_TYPE: | |
1904 | WALK_SUBTREE (TYPE_METHOD_BASETYPE (*tp)); | |
1905 | /* Fall through. */ | |
1906 | ||
1907 | case FUNCTION_TYPE: | |
1908 | WALK_SUBTREE (TREE_TYPE (*tp)); | |
1909 | { | |
1910 | tree arg = TYPE_ARG_TYPES (*tp); | |
1911 | ||
1912 | /* We never want to walk into default arguments. */ | |
1913 | for (; arg; arg = TREE_CHAIN (arg)) | |
1914 | WALK_SUBTREE (TREE_VALUE (arg)); | |
1915 | } | |
1916 | break; | |
1917 | ||
1918 | case ARRAY_TYPE: | |
1919 | WALK_SUBTREE (TREE_TYPE (*tp)); | |
6c624f7f | 1920 | WALK_SUBTREE_TAIL (TYPE_DOMAIN (*tp)); |
d4e4baa9 AO |
1921 | |
1922 | case INTEGER_TYPE: | |
1923 | WALK_SUBTREE (TYPE_MIN_VALUE (*tp)); | |
6c624f7f | 1924 | WALK_SUBTREE_TAIL (TYPE_MAX_VALUE (*tp)); |
d4e4baa9 AO |
1925 | |
1926 | case OFFSET_TYPE: | |
1927 | WALK_SUBTREE (TREE_TYPE (*tp)); | |
6c624f7f | 1928 | WALK_SUBTREE_TAIL (TYPE_OFFSET_BASETYPE (*tp)); |
d4e4baa9 | 1929 | |
d436bff8 AH |
1930 | #ifdef INLINER_FOR_JAVA |
1931 | case EXIT_BLOCK_EXPR: | |
1932 | WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 1)); | |
1933 | ||
1934 | case SAVE_EXPR: | |
1935 | WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 0)); | |
1936 | #endif /* INLINER_FOR_JAVA */ | |
1937 | ||
d4e4baa9 AO |
1938 | default: |
1939 | abort (); | |
1940 | } | |
1941 | ||
1942 | /* We didn't find what we were looking for. */ | |
1943 | return NULL_TREE; | |
1944 | ||
1945 | #undef WALK_SUBTREE | |
8bcefb43 | 1946 | #undef WALK_SUBTREE_TAIL |
d4e4baa9 AO |
1947 | } |
1948 | ||
d92b4486 | 1949 | /* Like walk_tree, but does not walk duplicate nodes more than |
d4e4baa9 AO |
1950 | once. */ |
1951 | ||
d92b4486 | 1952 | tree |
46c5ad27 | 1953 | walk_tree_without_duplicates (tree *tp, walk_tree_fn func, void *data) |
d4e4baa9 AO |
1954 | { |
1955 | tree result; | |
1956 | htab_t htab; | |
1957 | ||
1958 | htab = htab_create (37, htab_hash_pointer, htab_eq_pointer, NULL); | |
1959 | result = walk_tree (tp, func, data, htab); | |
1960 | htab_delete (htab); | |
1961 | return result; | |
1962 | } | |
1963 | ||
1964 | /* Passed to walk_tree. Copies the node pointed to, if appropriate. */ | |
1965 | ||
1966 | tree | |
46c5ad27 | 1967 | copy_tree_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) |
d4e4baa9 AO |
1968 | { |
1969 | enum tree_code code = TREE_CODE (*tp); | |
1970 | ||
1971 | /* We make copies of most nodes. */ | |
1972 | if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)) | |
d4e4baa9 | 1973 | || TREE_CODE_CLASS (code) == 'c' |
d4e4baa9 AO |
1974 | || code == TREE_LIST |
1975 | || code == TREE_VEC | |
69dcadff | 1976 | || (*lang_hooks.tree_inlining.tree_chain_matters_p) (*tp)) |
d4e4baa9 AO |
1977 | { |
1978 | /* Because the chain gets clobbered when we make a copy, we save it | |
1979 | here. */ | |
1980 | tree chain = TREE_CHAIN (*tp); | |
1981 | ||
1982 | /* Copy the node. */ | |
1983 | *tp = copy_node (*tp); | |
1984 | ||
1985 | /* Now, restore the chain, if appropriate. That will cause | |
1986 | walk_tree to walk into the chain as well. */ | |
1987 | if (code == PARM_DECL || code == TREE_LIST | |
d436bff8 | 1988 | #ifndef INLINER_FOR_JAVA |
69dcadff | 1989 | || (*lang_hooks.tree_inlining.tree_chain_matters_p) (*tp) |
009ed910 | 1990 | || STATEMENT_CODE_P (code)) |
d4e4baa9 AO |
1991 | TREE_CHAIN (*tp) = chain; |
1992 | ||
1993 | /* For now, we don't update BLOCKs when we make copies. So, we | |
1994 | have to nullify all scope-statements. */ | |
1995 | if (TREE_CODE (*tp) == SCOPE_STMT) | |
1996 | SCOPE_STMT_BLOCK (*tp) = NULL_TREE; | |
d436bff8 AH |
1997 | #else /* INLINER_FOR_JAVA */ |
1998 | || (*lang_hooks.tree_inlining.tree_chain_matters_p) (*tp)) | |
1999 | TREE_CHAIN (*tp) = chain; | |
2000 | #endif /* INLINER_FOR_JAVA */ | |
d4e4baa9 | 2001 | } |
3c2a7a6a | 2002 | else if (TREE_CODE_CLASS (code) == 't') |
d4e4baa9 AO |
2003 | *walk_subtrees = 0; |
2004 | ||
2005 | return NULL_TREE; | |
2006 | } | |
2007 | ||
2008 | /* The SAVE_EXPR pointed to by TP is being copied. If ST contains | |
2009 | information indicating to what new SAVE_EXPR this one should be | |
2010 | mapped, use that one. Otherwise, create a new node and enter it in | |
2011 | ST. FN is the function into which the copy will be placed. */ | |
2012 | ||
2013 | void | |
46c5ad27 | 2014 | remap_save_expr (tree *tp, void *st_, tree fn, int *walk_subtrees) |
d4e4baa9 AO |
2015 | { |
2016 | splay_tree st = (splay_tree) st_; | |
2017 | splay_tree_node n; | |
5e20bdd7 | 2018 | tree t; |
d4e4baa9 AO |
2019 | |
2020 | /* See if we already encountered this SAVE_EXPR. */ | |
2021 | n = splay_tree_lookup (st, (splay_tree_key) *tp); | |
d92b4486 | 2022 | |
d4e4baa9 AO |
2023 | /* If we didn't already remap this SAVE_EXPR, do so now. */ |
2024 | if (!n) | |
2025 | { | |
5e20bdd7 | 2026 | t = copy_node (*tp); |
d4e4baa9 AO |
2027 | |
2028 | /* The SAVE_EXPR is now part of the function into which we | |
2029 | are inlining this body. */ | |
2030 | SAVE_EXPR_CONTEXT (t) = fn; | |
2031 | /* And we haven't evaluated it yet. */ | |
2032 | SAVE_EXPR_RTL (t) = NULL_RTX; | |
2033 | /* Remember this SAVE_EXPR. */ | |
5e20bdd7 | 2034 | splay_tree_insert (st, (splay_tree_key) *tp, (splay_tree_value) t); |
350ebd54 | 2035 | /* Make sure we don't remap an already-remapped SAVE_EXPR. */ |
1593ad2e | 2036 | splay_tree_insert (st, (splay_tree_key) t, (splay_tree_value) t); |
d4e4baa9 AO |
2037 | } |
2038 | else | |
5e20bdd7 JZ |
2039 | { |
2040 | /* We've already walked into this SAVE_EXPR; don't do it again. */ | |
2041 | *walk_subtrees = 0; | |
2042 | t = (tree) n->value; | |
2043 | } | |
d4e4baa9 AO |
2044 | |
2045 | /* Replace this SAVE_EXPR with the copy. */ | |
5e20bdd7 | 2046 | *tp = t; |
d4e4baa9 | 2047 | } |
d436bff8 AH |
2048 | |
2049 | #ifdef INLINER_FOR_JAVA | |
2050 | /* Add STMT to EXISTING if possible, otherwise create a new | |
4b7e68e7 | 2051 | COMPOUND_EXPR and add STMT to it. */ |
d436bff8 AH |
2052 | |
2053 | static tree | |
46c5ad27 | 2054 | add_stmt_to_compound (tree existing, tree type, tree stmt) |
d436bff8 AH |
2055 | { |
2056 | if (!stmt) | |
2057 | return existing; | |
2058 | else if (existing) | |
2059 | return build (COMPOUND_EXPR, type, existing, stmt); | |
2060 | else | |
2061 | return stmt; | |
2062 | } | |
2063 | ||
2064 | #endif /* INLINER_FOR_JAVA */ |