diff options
Diffstat (limited to 'gcc/ada/gcc-interface/utils2.cc')
-rw-r--r-- | gcc/ada/gcc-interface/utils2.cc | 41 |
1 files changed, 36 insertions, 5 deletions
diff --git a/gcc/ada/gcc-interface/utils2.cc b/gcc/ada/gcc-interface/utils2.cc index 76622da..ae81a0d 100644 --- a/gcc/ada/gcc-interface/utils2.cc +++ b/gcc/ada/gcc-interface/utils2.cc @@ -2141,9 +2141,9 @@ build_call_alloc_dealloc_proc (tree gnu_obj, tree gnu_size, tree gnu_type, tree gnu_proc = gnat_to_gnu (gnat_proc); tree gnu_call; - /* A storage pool's underlying type is a record type (for both predefined - storage pools and GNAT simple storage pools). The secondary stack uses - the same mechanism, but its pool object (SS_Pool) is an integer. */ + /* A storage pool's underlying type is a record type for both predefined + storage pools and GNAT simple storage pools. The return and secondary + stacks use the same mechanism, but their pool object is an integer. */ if (Is_Record_Type (Underlying_Type (Etype (gnat_pool)))) { /* The size is the third parameter; the alignment is the @@ -2170,7 +2170,6 @@ build_call_alloc_dealloc_proc (tree gnu_obj, tree gnu_size, tree gnu_type, gnu_size, gnu_align); } - /* Secondary stack case. */ else { /* The size is the second parameter. */ @@ -2180,10 +2179,42 @@ build_call_alloc_dealloc_proc (tree gnu_obj, tree gnu_size, tree gnu_type, gnu_size = convert (gnu_size_type, gnu_size); + if (DECL_BUILT_IN_CLASS (gnu_proc) == BUILT_IN_FRONTEND + && DECL_FE_FUNCTION_CODE (gnu_proc) == BUILT_IN_RETURN_SLOT) + { + /* This must be an allocation of the return stack in a function that + returns by invisible reference. */ + gcc_assert (!gnu_obj); + gcc_assert (current_function_decl + && TREE_ADDRESSABLE (TREE_TYPE (current_function_decl))); + tree gnu_ret_size; + + gnu_call = DECL_RESULT (current_function_decl); + + /* The allocation has alreay been done by the caller so we check that + we are not going to overflow the return slot. */ + if (TYPE_CI_CO_LIST (TREE_TYPE (current_function_decl))) + gnu_ret_size + = TYPE_SIZE_UNIT + (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (TREE_TYPE (gnu_call))))); + else + gnu_ret_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (gnu_call))); + + gnu_call + = fold_build3 (COND_EXPR, TREE_TYPE (gnu_call), + fold_build2 (LE_EXPR, boolean_type_node, + fold_convert (sizetype, gnu_size), + gnu_ret_size), + gnu_call, + build_call_raise (PE_Explicit_Raise, Empty, + N_Raise_Program_Error)); + } + /* The first arg is the address of the object, for a deallocator, then the size. */ - if (gnu_obj) + else if (gnu_obj) gnu_call = build_call_n_expr (gnu_proc, 2, gnu_obj, gnu_size); + else gnu_call = build_call_n_expr (gnu_proc, 1, gnu_size); } |