From: Eric Botcazou <ebotcazou@adacore.com>
Adjusting the RESULT_DECL of functions is necessary before handing them over
to the middle-end when they return by invisible reference and are defined in
the current translation unit, so that's done in Subprogram_Body_to_gnu.
That's also needed when the functions are generated by the middle-end, like
GNU thunks. But, in this case, the transformation can only be applied when
the full view of the type is available, which is not guaranteed by the time
maybe_make_gnu_thunk is invoked, so the transformation needs to be delayed
and applied by update_profile when the full view is eventually encountered.
gcc/ada/ChangeLog:
PR ada/89609
* gcc-interface/gigi.h (adjust_result_decl_for_invisible_reference):
New inline function.
* gcc-interface/decl.cc (update_profile): Adjust the RESULT_DECL of
the function if it returns by invisible reference.
* gcc-interface/trans.cc (Subprogram_Body_to_gnu): Replace manual
adjustment by a call to adjust_result_decl_for_invisible_reference.
(maybe_make_gnu_thunk): Likewise.
* gcc-interface/targtyps.cc: Include stor-layout.h header file.
Tested on x86_64-pc-linux-gnu, committed on master.
---
gcc/ada/gcc-interface/decl.cc | 3 +++
gcc/ada/gcc-interface/gigi.h | 24 ++++++++++++++++++++++++
gcc/ada/gcc-interface/targtyps.cc | 1 +
gcc/ada/gcc-interface/trans.cc | 25 ++++---------------------
4 files changed, 32 insertions(+), 21 deletions(-)
@@ -6018,6 +6018,9 @@ update_profile (Entity_Id gnat_subprog)
DECL_ARGUMENTS (gnu_subprog) = gnu_param_list;
finish_subprog_decl (gnu_subprog, gnu_ext_name, gnu_type);
+
+ /* If the function returns by invisible reference, make it explicit. */
+ adjust_result_decl_for_invisible_reference (gnu_subprog);
}
}
@@ -1208,6 +1208,30 @@ return_type_with_variable_size_p (tree type)
return false;
}
+/* Adjust RESULT_DECL of a function that returns by invisible reference.
+
+ Adjusting the RESULT_DECL of functions is needed before handing them over
+ to the middle-end when they return by invisible reference and are defined
+ in the current translation unit, which is done in Subprogram_Body_to_gnu.
+
+ That's also needed when the functions are generated by the middle-end, like
+ GNU thunks. But, in this case, the transformation can only be applied when
+ the full view of the type is available, which is not guaranteed by the time
+ maybe_make_gnu_thunk is invoked, so the transformation needs to be delayed
+ and applied by update_profile when the full view is eventually seen. */
+
+static inline void
+adjust_result_decl_for_invisible_reference (tree subprog)
+{
+ if (TREE_ADDRESSABLE (TREE_TYPE (subprog))
+ && TREE_CODE (TREE_TYPE (DECL_RESULT (subprog))) != REFERENCE_TYPE)
+ {
+ TREE_TYPE (DECL_RESULT (subprog))
+ = build_reference_type (TREE_TYPE (DECL_RESULT (subprog)));
+ relayout_decl (DECL_RESULT (subprog));
+ }
+}
+
/* Return the unsigned version of TYPE_NODE, a scalar type. */
static inline tree
@@ -31,6 +31,7 @@
#include "tm.h"
#include "target.h"
#include "tree.h"
+#include "stor-layout.h"
#include "ada.h"
#include "types.h"
@@ -3995,17 +3995,8 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
else
gnu_return_var_elmt = NULL_TREE;
- /* If the function returns by invisible reference, make it explicit in the
- function body, but beware that maybe_make_gnu_thunk may already have done
- it if the function is inlined across units. See gnat_to_gnu_subprog_type
- for more details. */
- if (TREE_ADDRESSABLE (gnu_subprog_type)
- && TREE_CODE (TREE_TYPE (gnu_result_decl)) != REFERENCE_TYPE)
- {
- TREE_TYPE (gnu_result_decl)
- = build_reference_type (TREE_TYPE (gnu_result_decl));
- relayout_decl (gnu_result_decl);
- }
+ /* If the function returns by invisible reference, make it explicit. */
+ adjust_result_decl_for_invisible_reference (gnu_subprog);
/* Set the line number in the decl to correspond to that of the body. */
if (DECL_IGNORED_P (gnu_subprog))
@@ -11514,16 +11505,8 @@ maybe_make_gnu_thunk (Entity_Id gnat_thunk, tree gnu_thunk)
indirect_offset = (HOST_WIDE_INT) (POINTER_SIZE / BITS_PER_UNIT);
}
- /* If the target returns by invisible reference and is external, apply the
- same transformation as Subprogram_Body_to_gnu here. */
- if (TREE_ADDRESSABLE (TREE_TYPE (gnu_target))
- && DECL_EXTERNAL (gnu_target)
- && TREE_CODE (TREE_TYPE (DECL_RESULT (gnu_target))) != REFERENCE_TYPE)
- {
- TREE_TYPE (DECL_RESULT (gnu_target))
- = build_reference_type (TREE_TYPE (DECL_RESULT (gnu_target)));
- relayout_decl (DECL_RESULT (gnu_target));
- }
+ /* If the function returns by invisible reference, make it explicit. */
+ adjust_result_decl_for_invisible_reference (gnu_target);
/* The thunk expander requires the return types of thunk and target to be
compatible, which is not fully the case with the CICO mechanism. */