5.13.5.3.2.4.2.2. Generate code for initializing function parameters
Below create a splay tree for field decl_map , which is used to map local declarations of the inlined function to the counterparts in the function inlined into. At line 1393, if CALL_EXPR_HAS_RETURN_SLOT_ADDR is not 0, means that the address of the return slot is part of the argument list, and this slot is always at first in the list.
expand_call_inline (continue)
1384 /* Local declarations will be replaced by their equivalents in this
1385 map. */
1386 st = id->decl_map;
1387 id->decl_map = splay_tree_new (splay_tree_compare_pointers,
1388 NULL, NULL);
1389
1390 /* Initialize the parameters. */
1391 args = TREE_OPERAND (t, 1);
1392 return_slot_addr = NULL_TREE;
1393 if (CALL_EXPR_HAS_RETURN_SLOT_ADDR (t))
1394 {
1395 return_slot_addr = TREE_VALUE (args);
1396 args = TREE_CHAIN (args);
1397 }
1398
1399 #ifndef INLINER_FOR_JAVA
1400 arg_inits = initialize_inlined_parameters (id, args, fn);
1401 /* Expand any inlined calls in the initializers. Do this before we
1402 push FN on the stack of functions we are inlining; we want to
1403 inline calls to FN that appear in the initializers for the
1404 parameters. */
1405 expand_calls_inline (&arg_inits, id);
1406 /* And add them to the tree. */
1407 COMPOUND_BODY (stmt) = chainon (COMPOUND_BODY (stmt), arg_inits);
Like function invocation, though inline function is expanded within the caller’s body, its arguments may need be converted to the type of the parameter, or need extra code to get the copy. The job is done by below function.
718 static tree
719 #ifndef INLINER_FOR_JAVA
720 initialize_inlined_parameters (inline_data *id, tree args, tree fn) in tree-inline.c
721 #else /* INLINER_FOR_JAVA */
722 initialize_inlined_parameters (inline_data *id, tree args, tree fn, tree block)
723 #endif /* INLINER_FOR_JAVA */
724 {
725 tree init_stmts;
726 tree parms;
727 tree a;
728 tree p;
729 #ifdef INLINER_FOR_JAVA
730 tree vars = NULL_TREE;
731 #endif /* INLINER_FOR_JAVA */
732 int argnum = 0;
733
734 /* Figure out what the parameters are. */
735 parms =
736 DECL_ARGUMENTS (fn);
737
738 /* Start with no initializations whatsoever. * /
739 init_stmts = NULL_TREE;
740
741 /* Loop through the parameter declarations, replacing each with an
742 equivalent VAR_DECL, appropriately initialized. */
743 for (p = parms, a = args; p;
744 a = a ? TREE_CHAIN (a) : a, p = TREE_CHAIN (p))
745 {
746 #ifndef INLINER_FOR_JAVA
747 tree init_stmt;
748 tree cleanup;
749 #endif /* not INLINER_FOR_JAVA */
750 tree var;
751 tree value;
752 tree var_sub;
753
754 ++argnum;
755
756 /* Find the initializer. */
757 value = (*lang_hooks .tree_inlining.convert_parm_for_inlining)
758 (p, a ? TREE_VALUE (a) : NULL_TREE, fn, argnum);
759
760 /* If the parameter is never assigned to, we may not need to
761 create a new variable here at all. Instead, we may be able
762 to just use the argument value. */
763 if (TREE_READONLY (p)
764 && !TREE_ADDRESSABLE (p)
765 && value && !TREE_SIDE_EFFECTS (value))
766 {
767 /* Simplify the value, if possible. */
768 value = fold (DECL_P (value) ? decl_constant_value (value) : value);
769
770 /* We can't risk substituting complex expressions. They
771 might contain variables that will be assigned to later.
772 Theoretically, we could check the expression to see if
773 all of the variables that determine its value are
774 read-only, but we don't bother. */
775 if (TREE_CONSTANT (value) || TREE_READONLY_DECL_P (value))
776 {
777 /* If this is a declaration, wrap it a NOP_EXPR so that
778 we don't try to put the VALUE on the list of
779 BLOCK_VARS. */
780 if (DECL_P (value))
781 value = build1 (NOP_EXPR, TREE_TYPE (value), value);
782
783 /* If this is a constant, make sure it has the right type. */
784 else if (TREE_TYPE (value) != TREE_TYPE (p))
785 value = fold (build1 (NOP_EXPR, TREE_TYPE (p), value));
786
787 splay_tree_insert (id->decl_map,
788 (splay_tree_key) p,
789 (splay_tree_value) value);
790 continue ;
791 }
792 }
Above at line 757, hook convert_parm_for_inlining provides treatment for converting type from argument’s to parameter’s. However as C++ is a strong typing language (note that C is NOT), hook here does nothing.
Further, if the parameter is constant and its address isn’t taken, as long as the argument hasn’t side effect, it can use the argument’s value directly without constructing new local variable. In fact, GCC here behaviors alittle conservative, argument after constant-folding, it must be a constant or read-only, its value can be used directly. For qualified argument, we use NOP_EXPR to encapsulate them.
initialize_inlined_parameters (continue)
794 /* Make an equivalent VAR_DECL. */
795 var = copy_decl_for_inlining (p, fn, VARRAY_TREE (id->fns, 0));
796
797 /* See if the frontend wants to pass this by invisible reference. If
798 so, our new VAR_DECL will have REFERENCE_TYPE, and we need to
799 replace uses of the PARM_DECL with dereferences. */
800 if (TREE_TYPE (var) != TREE_TYPE (p)
801 && POINTER_TYPE_P (TREE_TYPE (var))
802 && TREE_TYPE (TREE_TYPE (var)) == TREE_TYPE (p))
803 var_sub = build1 (INDIRECT_REF, TREE_TYPE (p), var);
804 else
805 var_sub = var;
806
807 /* Register the VAR_DECL as the equivalent for the PARM_DECL;
808 that way, when the PARM_DECL is encountered, it will be
809 automatically replaced by the VAR_DECL. */
810 splay_tree_insert (id->decl_map,
811 (splay_tree_key) p,
812 (splay_tree_value) var_sub);
813
814 /* Declare this new variable. */
815 #ifndef INLINER_FOR_JAVA
816 init_stmt = build_stmt (DECL_STMT, var);
817 TREE_CHAIN (init_stmt) = init_stmts;
818 init_stmts = init_stmt;
819 #else /* INLINER_FOR_JAVA */
…
822 #endif /* INLINER_FOR_JAVA */
823
824 /* Initialize this VAR_DECL from the equivalent argument. If
825 the argument is an object, created via a constructor or copy,
826 this will not result in an extra copy: the TARGET_EXPR
827 representing the argument will be bound to VAR, and the
828 object will be constructed in VAR. */
829 if (! TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (p)))
830 #ifndef INLINER_FOR_JAVA
831 DECL_INITIAL (var) = value;
832 else
833 {
834 /* Even if P was TREE_READONLY, the new VAR should not be.
835 I n the original code, we would have constructed a
836 temporary, and then the function body would have never
837 changed the value of P. However, now, we will be
838 constructing VAR directly. The constructor body may
839 change its value multiple times as it is being
840 constructed. Therefore, it must not be TREE_READONLY;
841 the back-end assumes that TREE_READONLY variable is
842 assigned to only once. */
843 TREE_READONLY (var) = 0;
844
845 /* Build a run-time initialization. */
846 init_stmt = build_stmt (EXPR_STMT,
847 build (INIT_EXPR, TREE_TYPE (p),
848 var, value));
849 /* Add this initialization to the list. Note that we want the
850 declaration *after* the initialization because we are going
851 to reverse all the initialization statements below. */
852 TREE_CHAIN (init_stmt) = init_stmts;
853 init_stmts = init_stmt;
854 }
At line 795, copy_decl_for_inlining will, out from the parameter, builds a VAR_DECL of the same name, same type in the caller’s body. And line 816 makes the VAR_DECL created by copy_decl_for_inlining become a local ones. Thus, argument passing of this inlined function can be turned into assignment operation.
Next, case satisfying condition at line 800 is that, we pass an object to a parameter of reference type, so here we put the object into INDIRECT_REF.
initialize_inlined_parameters (continue)
856 /* See if we need to clean up the declaration. */
857 cleanup = (*lang_hooks .maybe_build_cleanup ) (var);
858 if (cleanup)
859 {
860 tree cleanup_stmt;
861 /* Build the cleanup statement. */
862 cleanup_stmt = build_stmt (CLEANUP_STMT, var, cleanup);
863 /* Add it to the *front* of the list; the list will be
864 reversed below. */
865 TREE_CHAIN (cleanup_stmt) = init_stmts;
866 init_stmts = cleanup_stmt;
867 }
868 #else /* INLINER_FOR_JAVA */
…
881 #endif /* INLINER_FOR_JAVA */
882 }
883
884 #ifndef INLINER_FOR_JAVA
885 /* Evaluate trailing arguments. */
886 for (; a; a = TREE_CHAIN (a))
887 {
888 tree init_stmt;
889 tree value = TREE_VALUE (a);
890
891 if (! value || ! TREE_SIDE_EFFECTS (value))
892 continue ;
893
894 init_stmt = build_stmt (EXPR_STMT, value);
895 TREE_CHAIN (init_stmt) = init_stmts;
896 init_stmts = init_stmt;
897 }
898
899 /* The initialization statements have been built up in reverse
900 order. Straighten them out now. */
901 return nreverse (init_stmts);
902 #else /* INLINER_FOR_JAVA */
…
905 #endif /* INLINER_FOR_JAVA */
906 }
If destorying the variable needs call destructor, code of this part is generated by hook at line 857. Loop at line 886 handles ellipsis arguments, as these arguments needs be processed via macros var_start, var_arg, var_end, unless the argument is declared as “volatile” (TREE_SIDE_EFFECTS is true), it needsn’t constructs a local variable for it (var_* macro are defined as __builtin_var_* in compiler).
At line 901, the list of initializing statements is returned, in which there may be invocation of inline function, so next calls expand_calls_inline upon these statements
5.13.5.3.2.4.2.3. Expand inline function
5.13.5.3.2.4.2.3.1. Prepare ret_label
At line 1431, DECL_INLINED_FNS records list of function inlined into fn 's body, it is set in optimize_inline_calls at time finishes processing the function (note we are now treating function calls fn , as we handle them in invocation order, fn should have been processed). Satisfying condition at lin 1431, it indicates fn hasn’t function inlined into, and fn is called by current function, so we add it into id->inlined_fns, in optimize_inline_calls , DECL_INLINED_FNS will be updated by the data.
expand_call_inline (continue)
1425 /* Record the function we are about to inline so that we can avoid
1426 recursing into it. */
1427 VARRAY_PUSH_TREE (id->fns, fn);
1428
1429 /* Record the function we are about to inline if optimize_function
1430 has not been called on it yet and we don't have it in the list. */
1431 if (! DECL_INLINED_FNS (fn))
1432 {
1433 int i;
1434
1435 for (i = VARRAY_ACTIVE_SIZE (id->inlined_fns) - 1; i >= 0; i--)
1436 if (VARRAY_TREE (id->inlined_fns, i) == fn)
1437 break ;
1438 if (i < 0)
1439 VARRAY_PUSH_TREE (id->inlined_fns, fn);
1440 }
1441
1442 /* Return statements in the function body will be replaced by jumps
1443 to the RET_LABEL. */
1444 id->ret_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
1445 DECL_CONTEXT (id->ret_label) = VARRAY_TREE (id->fns, 0);
1446
1447 if (! DECL_INITIAL (fn)
1448 || TREE_CODE (DECL_INITIAL (fn)) != BLOCK)
1449 abort ();
1450
1451 #ifndef INLINER_FOR_JAVA
1452 /* Create a block to put the parameters in. We have to do this
1453 after the parameters have been remapped because remapping
1454 parameters is different from remapping ordinary variables. */
1455 scope_stmt = build_stmt (SCOPE_STMT, DECL_INITIAL (fn));
1456 SCOPE_BEGIN_P (scope_stmt) = 1;
1457 SCOPE_NO_CLEANUPS_P (scope_stmt) = 1;
1458 remap_block (scope_stmt, DECL_ARGUMENTS (fn), id);
1459 TREE_CHAIN (scope_stmt) = COMPOUND_BODY (stmt);
1460 COMPOUND_BODY (stmt) = scope_stmt;
14161
1462 /* Tell the debugging backends that this block represents the
1463 outermost scope of the inlined function. */
1464 if (SCOPE_STMT_BLOCK (scope_stmt))
1465 BLOCK_ABSTRACT_ORIGIN (SCOPE_STMT_BLOCK (scope_stmt)) = DECL_ORIGIN (fn);
In optimize_inline_calls at line 1636, see that the first elmenet of id->fns is current function. Above line 1444 and 1445 construct a RET_LABEL lable, which is used to trun return statement of the called function into jump statement. At line 1447, DECL_INITIAL holds the tree of bindings, which if is valid, its first element must be a BLOCK. Above at line 1455 introduces a scope to enclose these arguments.
5.13.5.3.2.4.2.3.2. Replace parameters
Before, code for initializing arguments is ready, inlining function next to declare variables have the same name and type as parameters, and in the function body every parameter refernce should be updated to the corresponding variable. Declaring variables having the same name and type as parameters is done by remap_block at line 1458. In it, DECL_ARGUMENTS accesses the parameters list. And below at line 337, “SCOPE_STMT_BLOCK (scope_stmt)” in fact refers to “DECL_INITIAL (fn)”.
315 static void
316 #ifndef INLINER_FOR_JAVA
317 remap_block (tree scope_stmt, tree decls, inline_data *id) in tree-inline.c
…
320 #endif /* INLINER_FOR_JAVA */
321 {
322 #ifndef INLINER_FOR_JAVA
323 /* We cannot do this in the cleanup for a TARGET_EXPR since we do
324 not know whether or not expand_expr will actually write out the
325 code we put there. If it does not, then we'll have more BLOCKs
326 than block-notes, and things will go awry. At some point, we
327 should make the back-end handle BLOCK notes in a tidier way,
328 without requiring a strict correspondence to the block-tree; then
329 this check can go. */
330 if (id->in_target_cleanup_p)
331 {
332 SCOPE_STMT_BLOCK (scope_stmt) = NULL_TREE;
333 return ;
334 }
335
336 /* If this is the beginning of a scope, remap the associated BLOCK. */
337 if (SCOPE_BEGIN_P (scope_stmt) && SCOPE_STMT_BLOCK (scope_stmt))
338 {
339 tree old_block;
340 tree new_block;
341 tree old_var;
342 tree fn;
343
344 /* Make the new block. */
345 old_block = SCOPE_STMT_BLOCK (scope_stmt);
346 new_block = make_node (BLOCK);
347 TREE_USED (new_block) = TREE_USED (old_block);
348 BLOCK_ABSTRACT_ORIGIN (new_block) = old_block;
349 SCOPE_STMT_BLOCK (scope_stmt) = new_block;
350
351 /* Remap its variables. */
352 for (old_var = decls ? decls : BLOCK_VARS (old_block);
353 old_var;
354 old_var = TREE_CHAIN (old_var))
355 {
356 tree new_var;
357
358 /* Remap the variable. */
359 new_var = remap_decl (old_var, id);
360 /* If we didn't remap this variable, so we can't mess with
361 its TREE_CHAIN. If we remapped this variable to
362 something other than a declaration (say, if we mapped it
363 to a constant), then we must similarly omit any mention
364 of it here. */
365 if (!new_var || !DECL_P (new_var))
366 ;
367 else
368 {
369 TREE_CHAIN (new_var) = BLOCK_VARS (new_block);
370 BLOCK_VARS (new_block) = new_var;
371 }
372 }
Note that decls above is the parameter list (nodes of PARM_DECL), while invoking remap_block at other places argument decls is always NULL (in which case accessing local variables declaration by BLOCK_VARS). See that new_block is then the substitution of old_block (it’s the parameter list), it replaces old_block at line 349, parameters after copying and transforming are linked into new_block via BLOCK_VAR (line 570), thus complete declaring the variables having the same name and type as parameters within the function body.
Below is the procedure of copying and transforming.
133 static tree
134 remap_decl (tree decl, inline_data *id) in tree-inline.c
135 {
136 splay_tree_node n;
137 tree fn;
138
139 /* We only remap local variables in the current function. */
140 fn = VARRAY_TOP_TREE (id->fns);
141 if (! (*lang_hooks .tree_inlining.auto_var_in_fn_p ) (decl, fn))
142 return NULL_TREE;
At first, it needs find out auto variables in the funciton. Of course, different language has its own definition about auto variable, to C++, the hook is bound with below function (C, C++ have the same definition about auto variable, but due to different intermediate tree generated, they use different judge routines).
2136 int
2137 cp_auto_var_in_fn_p (tree var, tree fn) in tree.c
2138 {
2139 return (DECL_P (var) && DECL_CONTEXT (var) == fn
2140 && nonstatic_local_decl_p (var));
2141 }
If the declaraton had been copied, it is done; otherwise copy the node by copy_decl_for_inlining ( which copies PARM_DECL and RESULT_DECL into VAR_DECL). For *_DECL node, its TREE_TYPE may need deep copy.
remap_decl (continue)
144 /* See if we have remapped this declaration. */
145 n = splay_tree_lookup (id->decl_map, (splay_tree_key) decl);
146
147 /* If we didn't already have an equivalent for this declaration,
148 create one now. */
149 if (!n)
150 {
151 tree t;
152
153 /* Make a copy of the variable or label. */
154 t = copy_decl_for_inlining (decl, fn, VARRAY_TREE (id->fns, 0));
155
156 /* Remap types, if necessary. */
157 TREE_TYPE (t) = remap_type (TREE_TYPE (t), id);
158 if (TREE_CODE (t) == TYPE_DECL)
159 DECL_ORIGINAL_TYPE (t) = remap_type (DECL_ORIGINAL_TYPE (t), id);
160 else if (TREE_CODE (t) == PARM_DECL)
161 DECL_ARG_TYPE_AS_WRITTEN (t)
162 = remap_type (DECL_ARG_TYPE_AS_WRITTEN (t), id);
DECL_ORIGINAL_TYPE, for type defined via typedef, records the type in used. While for other types, this field is NULL. And DECL_ARG_TYPE_AS_WRITTEN holds the type as written (perhaps a function or array, but compiler generates pointer type appropriately). However here PARM_DECL won’t appear (as invoking copy_decl_for_inlining beforehand).
200 static tree
201 remap_type (tree type, inline_data *id) in tree-inline.c
202 {
203 splay_tree_node node;
204 tree new, t;
205
206 if (type == NULL)
207 return type;
208
209 /* See if we have remapped this type. */
210 node = splay_tree_lookup (id->decl_map, (splay_tree_key) type);
211 if (node)
212 return (tree) node->value;
213
214 /* The type only needs remapping if it's variably modified. */
215 if (! variably_modified_type_p (type))
216 {
217 splay_tree_insert (id->decl_map, (splay_tree_key) type,
218 (splay_tree_value) type);
219 return type;
220 }
221
222 /* We do need a copy. build and register it now. */
223 new = copy_node (type);
224 splay_tree_insert (id->decl_map, (splay_tree_key) type,
225 (splay_tree_value) new);
226
227 /* This is a new type, not a copy of an old type. Need to reassociate
228 variants. We can handle everything except the main variant lazily. */
229 t = TYPE_MAIN_VARIANT (type);
230 if (type != t)
231 {
232 t = remap_type (t, id);
233 TYPE_MAIN_VARIANT (new) = t;
234 TYPE_NEXT_VARIANT (new) = TYPE_MAIN_VARIANT (t);
235 TYPE_NEXT_VARIANT (t) = new;
236 }
237 else
238 {
239 TYPE_MAIN_VARIANT (new) = new;
240 TYPE_NEXT_VARIANT (new) = NULL;
241 }
242
243 /* Lazily create pointer and reference types. */
244 TYPE_POINTER_TO (new) = NULL;
245 TYPE_REFERENCE_TO (new) = NULL;
246
247 switch (TREE_CODE (new))
248 {
249 case INTEGER_TYPE:
250 case REAL_TYPE:
251 case ENUMERAL_TYPE:
252 case BOOLEAN_TYPE:
253 case CHAR_TYPE:
254 t = TYPE_MIN_VALUE (new);
255 if (t && TREE_CODE (t) != INTEGER_CST)
256 walk_tree (&TYPE_MIN_VALUE (new), copy_body_r , id, NULL);
257 t = TYPE_MAX_VALUE (new);
258 if (t && TREE_CODE (t) != INTEGER_CST)
259 walk_tree (&TYPE_MAX_VALUE (new), copy_body_r , id, NULL);
260 return new;
261
262 case POINTER_TYPE:
263 TREE_TYPE (new) = t = remap_type (TREE_TYPE (new), id);
264 if (TYPE_MODE (new) == ptr_mode)
265 TYPE_POINTER_TO (t) = new;
266 return new;
267
268 case REFERENCE_TYPE:
269 TREE_TYPE (new) = t = remap_type (TREE_TYPE (new), id);
270 if (TYPE_MODE (new) == ptr_mode)
271 TYPE_REFERENCE_TO (t) = new;
272 return new;
273
274 case METHOD_TYPE:
275 case FUNCTION_TYPE:
276 TREE_TYPE (new) = remap_type (TREE_TYPE (new), id);
277 walk_tree (&TYPE_ARG_TYPES (new), copy_body_r , id, NULL);
278 return new;
279
280 case ARRAY_TYPE:
281 TREE_TYPE (new) = remap_type (TREE_TYPE (new), id);
282 TYPE_DOMAIN (new) = remap_type (TYPE_DOMAIN (new), id);
283 break ;
284
285 case RECORD_TYPE:
286 case UNION_TYPE:
287 case QUAL_UNION_TYPE:
288 walk_tree (&TYPE_FIELDS (new), copy_body_r , id, NULL);
289 break ;
290
291 case FILE_TYPE:
292 case SET_TYPE:
293 case OFFSET_TYPE:
294 default :
295 /* Shouldn't have been thought variable sized. */
296 abort ();
297 }
298
299 walk_tree (&TYPE_SIZE (new), copy_body_r , id, NULL);
300 walk_tree (&TYPE_SIZE_UNIT (new), copy_body_r , id, NULL);
301
302 return new;
303 }
At copying and transforming parameters list, RETURN_STMT won’t be seen, and currently it is hard to understand the detail to transform RETURN_STMT into GOTO statement, so we skip this part temperarily. Below at line 578, local variables are also copied, as for every expansion, it should have its own instances of the variables.
502 static tree
503 copy_body_r (tree *tp, int *walk_subtrees, void *data) in tree-inline.c
504 {
505 inline_data* id;
506 tree fn;
507
508 /* Set up. */
509 id = (inline_data *) data;
510 fn = VARRAY_TOP_TREE (id->fns);
511
512 #if 0
…
519 #endif
520
521 #ifdef INLINER_FOR_JAVA
…
524 #endif
525
526 /* If this is a RETURN_STMT, change it into an EXPR_STMT and a
527 GOTO_STMT with the RET_LABEL as its target. */
528 #ifndef INLINER_FOR_JAVA
529 if (TREE_CODE (*tp) == RETURN_STMT && id->ret_label)
530 #else /* INLINER_FOR_JAVA */
…
532 #endif /* INLINER_FOR_JAVA */
533 {
…
571 }
572 /* Local variables and labels need to be replaced by equivalent
573 variables. We don't want to copy static variables; there's only
574 one of those, no matter how many times we inline the containing
575 function.
576 We do not also want to copy the label which we put into
577 GOTO_STMT which replaced RETURN_STMT. */
578 else if (*tp != id->ret_label
579 && (*lang_hooks .tree_inlining.auto_var_in_fn_p ) (*tp, fn))
580 {
581 tree new_decl;
582
583 /* Remap the declaration. */
584 new_decl = remap_decl (*tp, id);
585 if (! new_decl)
586 abort ();
587 /* Replace this variable with the copy. */
588 STRIP_TYPE_NOPS (new_decl);
589 *tp = new_decl;
590 }
591 #if 0
…
595 #endif
596 else if (TREE_CODE (*tp) == SAVE_EXPR)
597 remap_save_expr (tp, id->decl_map, VARRAY_TREE (id->fns, 0),
598 walk_subtrees);
599 else if (TREE_CODE (*tp) == UNSAVE_EXPR)
600 /* UNSAVE_EXPRs should not be generated until expansion time. */
601 abort ();
602 #ifndef INLINER_FOR_JAVA
603 /* For a SCOPE_STMT, we must copy the associated block so that we
604 can write out debugging information for the inlined variables. */
605 else if (TREE_CODE (*tp) == SCOPE_STMT && !id->in_target_cleanup_p)
606 copy_scope_stmt (tp, walk_subtrees, id);
607 #else /* INLINER_FOR_JAVA */
…
630 #endif /* INLINER_FOR_JAVA */
631 /* Types may need remapping as well. */
632 else if (TYPE_P (*tp))
633 *tp = remap_type (*tp, id);
634
635 /* Otherwise, just copy the node. Note that copy_tree_r already
636 knows not to copy VAR_DECLs, etc., so this is safe. */
637 else
638 {
639 if (TREE_CODE (*tp) == MODIFY_EXPR
640 && TREE_OPERAND (*tp, 0) == TREE_OPERAND (*tp, 1)
641 && ((*lang_hooks .tree_inlining.auto_var_in_fn_p )
642 (TREE_OPERAND (*tp, 0), fn)))
643 {
644 /* Some assignments VAR = VAR; don't generate any rtl code
645 and thus don't count as variable modification. Avoid
646 keeping bogosities like 0 = 0. */
647 tree decl = TREE_OPERAND (*tp, 0), value;
648 splay_tree_node n;
649
650 n = splay_tree_lookup (id->decl_map, (splay_tree_key) decl);
651 if (n)
652 {
653 value = (tree) n->value;
654 STRIP_TYPE_NOPS (value);
655 if (TREE_CONSTANT (value) || TREE_READONLY_DECL_P (value))
656 {
657 *tp = value;
658 return copy_body_r (tp, walk_subtrees, data);
659 }
660 }
661 }
662 else if (TREE_CODE (*tp) == ADDR_EXPR
663 && ((*lang_hooks .tree_inlining.auto_var_in_fn_p )
664 (TREE_OPERAND (*tp, 0), fn)))
665 {
666 /* Get rid of &* from inline substitutions. It can occur when
667 someone takes the address of a parm or return slot passed by
668 invisible reference. */
669 tree decl = TREE_OPERAND (*tp, 0), value;
670 splay_tree_node n;
671
672 n = splay_tree_lookup (id->decl_map, (splay_tree_key) decl);
673 if (n)
674 {
675 value = (tree) n->value;
676 if (TREE_CODE (value) == INDIRECT_REF)
677 {
678 *tp = convert (TREE_TYPE (*tp), TREE_OPERAND (value, 0));
679 return copy_body_r (tp, walk_subtrees, data);
680 }
681 }
682 }
683
684 copy_tree_r (tp, walk_subtrees, NULL);
685
686 TREE_TYPE (*tp) = remap_type (TREE_TYPE (*tp), id);
687
688 /* The copied TARGET_EXPR has never been expanded, even if the
689 original node was expanded already. */
690 if (TREE_CODE (*tp) == TARGET_EXPR && TREE_OPERAND (*tp, 3))
691 {
692 TREE_OPERAND (*tp, 1) = TREE_OPERAND (*tp, 3);
693 TREE_OPERAND (*tp, 3) = NULL_TREE;
694 }
695 }
696
697 /* Keep iterating. */
698 return NULL_TREE;
699 }
copy_body_r is always used as parameter of walk_tree , it goes into nodes via walk_tree . Obviously, for nodes walk_tree hasn’t idea how to work next step, copy_body_r should take the control itself, such as above SCOPE_STMT, SAVE_EXPR, MODIFY_EXPR and ADDR_EXPR etc. Note at line 639, the condition targets an expression of local variable: “var = var;’ (it may be created by macro expansion) which is meanless, here use the value after copying directly (line 672 takes the node created by copy). It is same for ADDR_EXPR of local variable, the referred object needs be replaced by object created by copy.
Note that walk_tree won’t invoke the passed function on constant node, and in remap_type , it won’t copy INTEGER_CST in the node (see in before, INTEGER_CST nodes are shared).
remap_decl (continue)
164 /* Remap sizes as necessary. */
165 walk_tree (&DECL_SIZE (t), copy_body_r , id, NULL);
166 walk_tree (&DECL_SIZE_UNIT (t), copy_body_r , id, NULL);
167
168 #ifndef INLINER_FOR_JAVA
169 if (! DECL_NAME (t) && TREE_TYPE (t)
170 && (*lang_hooks .tree_inlining.anon_aggr_type_p) (TREE_TYPE (t)))
171 {
172 /* For a VAR_DECL of anonymous type, we must also copy the
173 member VAR_DECLS here and rechain the DECL_ANON_UNION_ELEMS. */
174 tree members = NULL;
175 tree src;
176
177 for (src = DECL_ANON_UNION_ELEMS (t); src;
178 src = TREE_CHAIN (src))
179 {
180 tree member = remap_decl (TREE_VALUE (src), id);
181
182 if (TREE_PURPOSE (src))
183 abort ();
184 members = tree_cons (NULL, member, members);
185 }
186 DECL_ANON_UNION_ELEMS (t) = nreverse (members);
187 }
188 #endif /* not INLINER_FOR_JAVA */
189
190 /* Remember it, so that if we encounter this local entity
191 again we can reuse this copy. */
192 n = splay_tree_insert (id->decl_map,
193 (splay_tree_key) decl,
194 (splay_tree_value) t);
195 }
196
197 return (tree) n->value;
198 }
Similarly, for DECL_SIZE and DECL_SIZE_UNIT using INTEGER_CST, walk_tree skips them. At line 192, decl is the object being copied, and t is the object created by copy.
Back remap_block , when local variables corresponding to parameters are ready, at line 374 restore the order of the variables. And at line 376, id->cloning_p only is set in the invocation by clone_body (which invoked to clone constructor or destructor), at which time we are in the stage of parsing function being cloned. Obvious, in our scenario here, id->cloning_p is 0, and insert new_block after DECL_INITIAL.
remap_block (continue)
373 /* We put the BLOCK_VARS in reverse order; fix that now. */
374 BLOCK_VARS (new_block) = nreverse (BLOCK_VARS (new_block));
375 fn = VARRAY_TREE (id->fns, 0);
376 if (id->cloning_p)
377 /* We're building a clone; DECL_INITIAL is still
378 error_mark_node, and current_binding_level is the parm
379 binding level. */
380 (*lang_hooks .decls.insert_block) (new_block);
381 else
382 {
383 /* Attach this new block after the DECL_INITIAL block for the
384 function into which this block is being inlined. In
385 rest_of_compilation we will straighten out the BLOCK tree. */
386 tree *first_block;
387 if (DECL_INITIAL (fn))
388 first_block = &BLOCK_CHAIN (DECL_INITIAL (fn));
389 else
390 first_block = &DECL_INITIAL (fn);
391 BLOCK_CHAIN (new_block) = *first_block;
392 *first_block = new_block;
393 }
394 /* Remember the remapped block. */
395 splay_tree_insert (id->decl_map,
396 (splay_tree_key) old_block,
397 (splay_tree_value) new_block);
398 }
399 /* If this is the end of a scope, set the SCOPE_STMT_BLOCK to be the
400 remapped block. */
401 else if (SCOPE_END_P (scope_stmt) && SCOPE_STMT_BLOCK (scope_stmt))
402 {
403 splay_tree_node n;
404
405 /* Find this block in the table of remapped things. */
406 n = splay_tree_lookup (id->decl_map,
407 (splay_tree_key) SCOPE_STMT_BLOCK (scope_stmt));
408 if (! n)
409 abort ();
410 SCOPE_STMT_BLOCK (scope_stmt) = (tree) n->value;
411 }
412 #else /* INLINER_FOR_JAVA */
…
474 #endif /* INLINER_FOR_JAVA */
475 }
SCOPE_STMT_BLOCK containing the declarations contained in this scope, in scope_stmt with SCOPE_END_P held, it is the block enclosed by scope_stmt (refer to do_poplevel ). This block must be remapped already, using new block to replace the old one.