5.13.5.3.2.4.2.3.3. Construct variable for return value
After adding local variables for parameters, immediately declare (possible) variable for return value.
expand_call_inline (continue)
1467 /* Declare the return variable for the function. */
1468 COMPOUND_BODY (stmt)
1469 = chainon (COMPOUND_BODY (stmt),
1470 declare_return_variable (id, return_slot_addr, &use_stmt));
1471 #else /* INLINER_FOR_JAVA */
….
1483 #endif /* INLINER_FOR_JAVA */
Above return_slot_addr , if applying named return value optimziation (NRVO) to return aggregate object, is the slot for returning this object; otherwise is NULL (previous when copying parameters list, we remove this slot from processing).
913 #ifndef INLINER_FOR_JAVA
914 static tree
915 declare_return_variable (struct inline_data *id, tree return_slot_addr, in tree-inline.c
916 tree *use_stmt)
917 #else /* INLINER_FOR_JAVA */
…
921 #endif /* INLINER_FOR_JAVA */
922 {
923 tree fn = VARRAY_TOP_TREE (id->fns);
924 tree result = DECL_RESULT (fn);
925 #if ndef INLINER_FOR_JAVA
926 tree var;
927 #endif /* not INLINER_FOR_JAVA */
928 int need_return_decl = 1;
929
930 /* We don't need to do anything for functions that don't return
931 anything. */
932 if (!result || VOID_TYPE_P (TREE_TYPE (result)))
933 {
934 #ifndef INLINER_FOR_JAVA
935 *use_stmt = NULL_TREE;
936 #else /* INLINER_FOR_JAVA */
…
938 #endif /* INLINER_FOR_JAVA */
939 return NULL_TREE;
940 }
941
942 #ifndef INLINER_FOR_JAVA
943 var = ((*lang_hooks .tree_inlining.copy_res_decl_for_inlining )
944 (result, fn, VARRAY_TREE (id->fns, 0), id->decl_map,
945 &need_return_decl, return_slot_addr));
946
947 /* Register the VAR_DECL as the equivalent for the RESULT_DECL; that
948 way, when the RESULT_DECL is encountered, it will be
949 automatically replaced by the VAR_DECL. */
950 splay_tree_insert (id->decl_map,
951 (splay_tree_key) result,
952 (splay_tree_value) var);
953
954 /* Build the USE_STMT. If the return type of the function was
955 promoted, convert it back to the expected type. */
956 if (TREE_TYPE (var) == TREE_TYPE (TREE_TYPE (fn)))
957 *use_stmt = build_stmt (EXPR_STMT, var);
958 else
959 *use_stmt = build_stmt (EXPR_STMT,
960 build1 (NOP_EXPR, TREE_TYPE (TREE_TYPE (fn)),
961 var));
962 TREE_ADDRESSABLE (*use_stmt) = 1;
963
964 /* Build the declaration statement if FN does not return an
965 aggregate. */
966 if (need_return_decl)
967 return build_stmt (DECL_STMT, var);
968 #else /* INLINER_FOR_JAVA */
...
979 #endif /* INLINER_FOR_JAVA */
980 /* If FN does return an aggregate, there's no need to declare the
981 return variable; we're using a variable in our caller's frame. */
982 else
983 return NULL_TREE;
984 }
If there is no return value or it is NULL, of course need do nothing, or need copy the return value. In calling below function, result is the declaration of the function return value, fn is the function currently called, caller is the caller. As at calling function returning aggregate object, the caller needs to pass in the return slot (the way NRVO takes), this variable is declared by the caller, we needn’t care about it; but for other return value, we need declare variable for them here, and thus set need_decl (line 2171).
2147 tree
2148 cp_copy_res_decl_for_inlining (tree result, in tree.c
2149 tree fn,
2150 tree caller,
2151 void* decl_map_,
2152 int* need_decl,
2153 tree return_slot_addr)
2154 {
2155 splay_tree decl_map = (splay_tree)decl_map_;
2156 tree var;
2157
2158 /* If FN returns an aggregate then the caller will always pass the
2159 address of the return slot explicitly. If we were just to
2160 create a new VAR_DECL here, then the result of this function
2161 would be copied (bitwise) into the variable initialized by the
2162 TARGET_EXPR. That's incorrect, so we must transform any
2163 references to the RESULT into references to the target. */
2164
2165 /* We should have an explicit return slot iff the return type is
2166 TREE_ADDRESSABLE. See simplify_aggr_init_expr. */
2167 if (TREE_ADDRESSABLE (TREE_TYPE (result))
2168 != (return_slot_addr != NULL_TREE))
2169 abort ();
2170
2171 *need_decl = !return_slot_addr;
2172 if (return_slot_addr)
2173 {
2174 var = build_indirect_ref (return_slot_addr, "");
2175 if (! same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (var),
2176 TREE_TYPE (result)))
2177 abort ();
2178 }
2179 /* Otherwise, make an appropriate copy. */
2180 else
2181 var = copy_decl_for_inlining (result, fn, caller);
2182
2183 if (DECL_SAVED_FUNCTION_DATA (fn))
2184 {
2185 tree nrv = DECL_SAVED_FUNCTION_DATA (fn)->x_return_value;
2186 if (nrv)
2187 {
2188 /* We have a named return value; copy the name and source
2189 position so we can get reasonable debugging information, and
2190 register the return variable as its equivalent. */
2191 if (TREE_CODE (var) == VAR_DECL
2192 /* But not if we're initializing a variable from the
2193 enclosing function which already has its own name. */
2194 && DECL_NAME (var) == NULL_TREE)
2195 {
2196 DECL_NAME (var) = DECL_NAME (nrv);
2197 DECL_SOURCE_LOCATION (var) = DECL_SOURCE_LOCATION (nrv);
2198 DECL_ABSTRACT_ORIGIN (var) = DECL_ORIGIN (nrv);
2199 /* Don't lose initialization info. */
2200 DECL_INITIAL (var) = DECL_INITIAL (nrv);
2201 /* Don't forget that it needs to go in the stack. */
2202 TREE_ADDRESSABLE (var) = TREE_ADDRESSABLE (nrv);
2203 }
2204
2205 splay_tree_insert (decl_map,
2206 (splay_tree_key) nrv,
2207 (splay_tree_value) var);
2208 }
2209 }
2210
2211 return var;
2212 }
DECL_SAVED_FUNCTION_DATA saves the language_function objeect describing the function (it is set save_function_data in called by finsh_function ). In it field x_return_value is designed for NRVO purpose (which is set as return value in check_return_expr ). As at line 2174 INDIRECT_REF has been created for the object reffered by return_slot_addr , which is the object really used for return value, so set it according to field x_return_value, then update x_return_value by it.
If the return value needsn’t declaration, declare_return_variable will return NULL, or will return the corresponding DECL_STMT, which is inserted after variables for parameters at line 1470 in expand_call_inline . While use_stmt will be added in at the end of the expansion (as the associated target of ret_label).
5.13.5.3.2.4.2.3.4. Copy function body
With declaring local variables for parameters and return value, it can copy the function body and at the same time replacing the parameters and the return value, which is done by copy_body below.
expand_call_inline (continue)
1485 /* After we've initialized the parameters, we insert the body of the
1486 function itself. */
1487 #ifndef INLINER_FOR_JAVA
1488 inlined_body = &COMPOUND_BODY (stmt);
1489 while (*inlined_body)
1490 inlined_body = &TREE_CHAIN (*inlined_body);
1491 *inlined_body = copy_body (id);
1492 #else /* INLINER_FOR_JAVA */
…
1503 #endif /* INLINER_FOR_JAVA */
1504
1505 /* After the body of the function comes the RET_LABEL. This must come
1506 before we evaluate the returned value below, because that evaluation
1507 may cause RTL to be generated. */
1508 #ifndef INLINER_FOR_JAVA
1509 COMPOUND_BODY (stmt)
1510 = chainon (COMPOUND_BODY (stmt),
1511 build_stmt (LABEL_STMT, id->ret_label));
1512 #else /* INLINER_FOR_JAVA */
…
1519 #endif /* INLINER_FOR_JAVA */
1520
1521 /* Finally, mention the returned value so that the value of the
1522 statement-expression is the returned value of the function. */
1523 #ifndef INLINER_FOR_JAVA
1524 COMPOUND_BODY (stmt) = chainon (COMPOUND_BODY (stmt), use_stmt);
1525
1526 /* Close the block for the parameters. */
1527 scope_stmt = build_stmt (SCOPE_STMT, DECL_INITIAL (fn));
1528 SCOPE_NO_CLEANUPS_P (scope_stmt) = 1;
1529 remap_block (scope_stmt, NULL_TREE, id);
1530 COMPOUND_BODY (stmt)
1531 = chainon (COMPOUND_BODY (stmt), scope_stmt);
1532 #else /* INLINER_FOR_JAVA */
DECL_SAVED_TREE 保存的就是代表函数体的 COMPOUND_STMT 或对等物。
704 static tree
705 copy_body (inline_data *id) in tree-inline.c
706 {
707 tree body;
708
709 body = DECL_SAVED_TREE (VARRAY_TOP_TREE (id->fns));
710 walk_tree (&body, copy_body_r , id, NULL);
711
712 return body;
713 }
We have seen the most part of copy_body_r before, except below treatment of RETURN_STMT. Here first building a GOTO_STMT for ret_label prepared beforehand. If there is return value, it needs to insert EXPR_STMT of the return expression before GOTO_STMT.
copy_body_r (continue)
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 {
534 tree return_stmt = *tp;
535 tree goto_stmt;
536
537 /* Build the GOTO_STMT. */
538 #ifndef INLINER_FOR_JAVA
539 goto_stmt = build_stmt (GOTO_STMT, id->ret_label);
540 TREE_CHAIN (goto_stmt) = TREE_CHAIN (return_stmt);
541 GOTO_FAKE_P (goto_stmt) = 1;
542 #else /* INLINER_FOR_JAVA */
…
546 #endif /* INLINER_FOR_JAVA */
547
548 /* If we're returning something, just turn that into an
549 assignment into the equivalent of the original
550 RESULT_DECL. */
551 #ifndef INLINER_FOR_JAVA
552 if (RETURN_STMT_EXPR (return_stmt))
553 {
554 *tp = build_stmt (EXPR_STMT,
555 RETURN_STMT_EXPR (return_stmt));
556 STMT_IS_FULL_EXPR_P (*tp) = 1;
557 /* And then jump to the end of the function. */
558 TREE_CHAIN (*tp) = goto_stmt;
559 }
560 #else /* INLINER_FOR_JAVA */
…
567 #endif /* INLINER_FOR_JAVA */
568 /* If we're not returning anything just do the jump. */
569 else
570 *tp = goto_stmt;
Here RETURN_STMT is replaced by (possible) EXPR_STMT and GOTO_STMT, but its content is recorded by field RETURN_STMT_EXPR, which is now included by the EXPR_STMT. See that copy_body_r always returns 0, so walk_tree will still enter these new STMT nodes (walk_tree does pre-order traversal), and replaces the RETURN_DECL contained.
After copying, transforming the function body, attaches use_stmt prepared before. Thus expanding the inline function will get the result as:
double retVal = inline_f1 (int a1, short a2) =>
double retVal = { int a1; short a2; double `anon var`; { `copy and transform body` }; ret_lable: ` anon var `; }
expand_call_inline (continue)
1547 /* Clean up. */
1548 splay_tree_delete (id->decl_map);
1549 id->decl_map = st;
1550
1551 /* Although, from the semantic viewpoint, the new expression has
1552 side-effects only if the old one did, it is not possible, from
1553 the technical viewpoint, to evaluate the body of a function
1554 multiple times without serious havoc. */
1555 TREE_SIDE_EFFECTS (expr) = 1;
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. */
1560 #ifndef INLINER_FOR_JAVA
1561 chain = TREE_CHAIN (*tp);
1562 #endif /* INLINER_FOR_JAVA */
1563 *tp = build_expr_wfl (expr, DECL_SOURCE_FILE (fn), DECL_SOURCE_LINE (fn),
1564 /*col=*/ 0);
1565 EXPR_WFL_EMIT_LINE_NOTE (*tp) = 1;
1566 #ifndef INLINER_FOR_JAVA
1567 TREE_CHAIN (*tp) = chain;
1568 #endif /* not INLINER_FOR_JAVA */
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
1576 /* Update callgraph if needed. */
1577 if (id->decl)
1578 {
1579 cgraph_remove_call (id->decl, fn);
1580 cgraph_create_edges (id->decl, *inlined_body);
1581 }
1582
1583 /* Recurse into the body of the just inlined function. */
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 }
1590 VARRAY_POP (id->fns);
1591
1592 /* Don't walk into subtrees. We've already handled them above. */
1593 *walk_subtrees = 0;
1594
1595 (*lang_hooks .tree_inlining.end_inlining) (fn);
1596
1597 /* Keep iterating. */
1598 return NULL_TREE;
1599 }
Above inlined_body points to the expanded body, as in which may contain CALL_EXPR, continue to use expand_calls_inline to expand these inline functions. See that expand_calls_inline always returns NULL, it expects walk_tree to traverse the caller entirely.