diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2010-04-08 20:16:36 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2010-04-08 20:16:36 +0000 |
commit | d47d0a8d97e00479a3efd3913bc996f319ac8139 (patch) | |
tree | 3bbe3665b3ad0f65e64b4973b9c1ddee13f15d9a /gcc/ada/gcc-interface/decl.c | |
parent | dc5ee869f578f51a2691833b4d60054bf7e2a0a9 (diff) | |
download | gcc-d47d0a8d97e00479a3efd3913bc996f319ac8139.zip gcc-d47d0a8d97e00479a3efd3913bc996f319ac8139.tar.gz gcc-d47d0a8d97e00479a3efd3913bc996f319ac8139.tar.bz2 |
tree.h (TREE_ADDRESSABLE): Document its effect for function types.
* tree.h (TREE_ADDRESSABLE): Document its effect for function types.
* calls.c (expand_call): Pass the function type to aggregate_value_p.
* function.c (aggregate_value_p): Do not honor DECL_BY_REFERENCE on
the target function of a CALL_EXPR. Honor TREE_ADDRESSABLE on the
function type instead. Reorder and simplify checks.
* gimplify.c (gimplify_modify_expr_rhs) <WITH_SIZE_EXPR>: New case.
ada/
* gcc-interface/ada-tree.h (TYPE_RETURNS_UNCONSTRAINED_P): Rename into.
(TYPE_RETURN_UNCONSTRAINED_P): ...this.
(TYPE_RETURNS_BY_REF_P): Rename into.
(TYPE_RETURN_BY_DIRECT_REF_P): ...this.
(TYPE_RETURNS_BY_TARGET_PTR_P): Delete.
* gcc-interface/gigi.h (create_subprog_type): Adjust parameter names.
(build_return_expr): Likewise.
* gcc-interface/decl.c (gnat_to_gnu_entity) <E_Subprogram_Type>:
Rename local variables. If the return Mechanism is By_Reference, pass
return_by_invisible_ref_p to create_subprog_type instead of toggling
TREE_ADDRESSABLE. Test return_by_invisible_ref_p in order to annotate
the mechanism. Use regular return for contrained types with non-static
size and return by invisible reference for unconstrained return types
with default discriminants. Update comment.
* gcc-interface/trans.c (Subprogram_Body_to_gnu): If the function
returns by invisible reference, turn the RESULT_DECL into a pointer.
Do not handle DECL_BY_REF_P in the CICO case here.
(call_to_gnu): Remove code handling return by target pointer. For a
function call, if the return type has non-constant size, generate the
assignment with an INIT_EXPR.
(gnat_to_gnu) <N_Return_Statement>: Remove dead code in the CICO case.
If the function returns by invisible reference, build the copy return
operation manually.
(add_decl_expr): Initialize the variable with an INIT_EXPR.
* gcc-interface/utils.c (create_subprog_type): Adjust parameter names.
Adjust for renaming of macros. Copy the node only when necessary.
(create_subprog_decl): Do not toggle TREE_ADDRESSABLE on the return
type, only change DECL_BY_REFERENCE on the RETURN_DECL.
(convert_from_reference): Delete.
(is_byref_result): Likewise.
(gnat_genericize_r): Likewise.
(gnat_genericize): Likewise.
(end_subprog_body): Do not call gnat_genericize.
* gcc-interface/utils2.c (build_binary_op) <INIT_EXPR>: New case.
(build_return_expr): Adjust parameter names, logic and comment.
From-SVN: r158139
Diffstat (limited to 'gcc/ada/gcc-interface/decl.c')
-rw-r--r-- | gcc/ada/gcc-interface/decl.c | 114 |
1 files changed, 58 insertions, 56 deletions
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index 6da9ce4..25b4c07 100644 --- a/gcc/ada/gcc-interface/decl.c +++ b/gcc/ada/gcc-interface/decl.c @@ -6,7 +6,7 @@ * * * C Implementation File * * * - * Copyright (C) 1992-2009, Free Software Foundation, Inc. * + * Copyright (C) 1992-2010, Free Software Foundation, Inc. * * * * GNAT is free software; you can redistribute it and/or modify it under * * terms of the GNU General Public License as published by the Free Soft- * @@ -3799,13 +3799,13 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) tree gnu_field_list = NULL_TREE; /* Non-null for subprograms containing parameters passed by copy-in copy-out (Ada In Out or Out parameters not passed by reference), - in which case it is the list of nodes used to specify the values of - the in out/out parameters that are returned as a record upon + in which case it is the list of nodes used to specify the values + of the In Out/Out parameters that are returned as a record upon procedure return. The TREE_PURPOSE of an element of this list is a field of the record and the TREE_VALUE is the PARM_DECL corresponding to that field. This list will be saved in the TYPE_CI_CO_LIST field of the FUNCTION_TYPE node we create. */ - tree gnu_return_list = NULL_TREE; + tree gnu_cico_list = NULL_TREE; /* If an import pragma asks to map this subprogram to a GCC builtin, this is the builtin DECL node. */ tree gnu_builtin_decl = NULL_TREE; @@ -3831,9 +3831,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) && Is_Pure (gnat_entity)); bool volatile_flag = No_Return (gnat_entity); - bool returns_by_ref = false; - bool returns_unconstrained = false; - bool returns_by_target_ptr = false; + bool return_by_direct_ref_p = false; + bool return_by_invisi_ref_p = false; + bool return_unconstrained_p = false; bool has_copy_in_out = false; bool has_stub = false; int parmnum; @@ -3885,37 +3885,39 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) if (kind == E_Function || kind == E_Subprogram_Type) gnu_return_type = gnat_to_gnu_type (Etype (gnat_entity)); - /* If this function returns by reference, make the actual - return type of this function the pointer and mark the decl. */ + /* If this function returns by reference, make the actual return + type of this function the pointer and mark the decl. */ if (Returns_By_Ref (gnat_entity)) { - returns_by_ref = true; gnu_return_type = build_pointer_type (gnu_return_type); + return_by_direct_ref_p = true; } - /* If the Mechanism is By_Reference, ensure the return type uses - the machine's by-reference mechanism, which may not the same - as above (e.g., it might be by passing a fake parameter). */ - else if (kind == E_Function - && Mechanism (gnat_entity) == By_Reference) - { - TREE_ADDRESSABLE (gnu_return_type) = 1; - - /* We expect this bit to be reset by gigi shortly, so can avoid a - type node copy here. This actually also prevents troubles with - the generation of debug information for the function, because - we might have issued such info for this type already, and would - be attaching a distinct type node to the function if we made a - copy here. */ - } - - /* If we are supposed to return an unconstrained array, - actually return a fat pointer and make a note of that. Return - a pointer to an unconstrained record of variable size. */ + /* If the Mechanism is By_Reference, ensure this function uses the + target's by-invisible-reference mechanism, which may not be the + same as above (e.g. it might be passing an extra parameter). + + Prior to GCC 4, this was handled by just setting TREE_ADDRESSABLE + on the result type. Everything required to pass by invisible + reference using the target's mechanism (e.g. an extra parameter) + was handled at RTL expansion time. + + This doesn't work with GCC 4 any more for several reasons. First, + the gimplification process might need to create temporaries of this + type and the gimplifier ICEs on such attempts; that's why the flag + is now set on the function type instead. Second, the middle-end + now also relies on a different attribute, DECL_BY_REFERENCE on the + RESULT_DECL, and expects the by-invisible-reference-ness to be made + explicit in the function body. */ + else if (kind == E_Function && Mechanism (gnat_entity) == By_Reference) + return_by_invisi_ref_p = true; + + /* If we are supposed to return an unconstrained array, actually return + a fat pointer and make a note of that. */ else if (TREE_CODE (gnu_return_type) == UNCONSTRAINED_ARRAY_TYPE) { gnu_return_type = TREE_TYPE (gnu_return_type); - returns_unconstrained = true; + return_unconstrained_p = true; } /* If the type requires a transient scope, the result is allocated @@ -3924,7 +3926,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) else if (Requires_Transient_Scope (Etype (gnat_entity))) { gnu_return_type = build_pointer_type (gnu_return_type); - returns_unconstrained = true; + return_unconstrained_p = true; } /* If the type is a padded type and the underlying type would not @@ -3936,20 +3938,17 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) || Has_Foreign_Convention (gnat_entity))) gnu_return_type = TREE_TYPE (TYPE_FIELDS (gnu_return_type)); - /* If the return type has a non-constant size, we convert the function - into a procedure and its caller will pass a pointer to an object as - the first parameter when we call the function. This can happen for - an unconstrained type with a maximum size or a constrained type with - a size not known at compile time. */ - if (TYPE_SIZE_UNIT (gnu_return_type) - && !TREE_CONSTANT (TYPE_SIZE_UNIT (gnu_return_type))) + /* If the return type is unconstrained, that means it must have a + maximum size. Use the padded type as the effective return type. + And ensure the function uses the target's by-invisible-reference + mechanism to avoid copying too much data when it returns. */ + if (CONTAINS_PLACEHOLDER_P (TYPE_SIZE (gnu_return_type))) { - returns_by_target_ptr = true; - gnu_param_list - = create_param_decl (get_identifier ("TARGET"), - build_reference_type (gnu_return_type), - true); - gnu_return_type = void_type_node; + gnu_return_type + = maybe_pad_type (gnu_return_type, + max_size (TYPE_SIZE (gnu_return_type), true), + 0, gnat_entity, false, false, false, true); + return_by_invisi_ref_p = true; } /* If the return type has a size that overflows, we cannot have @@ -4091,8 +4090,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) &DECL_SOURCE_LOCATION (gnu_field)); TREE_CHAIN (gnu_field) = gnu_field_list; gnu_field_list = gnu_field; - gnu_return_list = tree_cons (gnu_field, gnu_param, - gnu_return_list); + gnu_cico_list + = tree_cons (gnu_field, gnu_param, gnu_cico_list); } } @@ -4105,8 +4104,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) /* If we have a CICO list but it has only one entry, we convert this function into a function that simply returns that one object. */ - if (list_length (gnu_return_list) == 1) - gnu_return_type = TREE_TYPE (TREE_PURPOSE (gnu_return_list)); + if (list_length (gnu_cico_list) == 1) + gnu_return_type = TREE_TYPE (TREE_PURPOSE (gnu_cico_list)); if (Has_Stdcall_Convention (gnat_entity)) prepend_one_attribute_to @@ -4131,22 +4130,25 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) gnu_param_list = nreverse (gnu_param_list); if (has_stub) gnu_stub_param_list = nreverse (gnu_stub_param_list); - gnu_return_list = nreverse (gnu_return_list); + gnu_cico_list = nreverse (gnu_cico_list); if (Ekind (gnat_entity) == E_Function) - Set_Mechanism (gnat_entity, - (returns_by_ref || returns_unconstrained - ? By_Reference : By_Copy)); + Set_Mechanism (gnat_entity, return_unconstrained_p + || return_by_direct_ref_p + || return_by_invisi_ref_p + ? By_Reference : By_Copy); gnu_type = create_subprog_type (gnu_return_type, gnu_param_list, - gnu_return_list, returns_unconstrained, - returns_by_ref, returns_by_target_ptr); + gnu_cico_list, return_unconstrained_p, + return_by_direct_ref_p, + return_by_invisi_ref_p); if (has_stub) gnu_stub_type = create_subprog_type (gnu_return_type, gnu_stub_param_list, - gnu_return_list, returns_unconstrained, - returns_by_ref, returns_by_target_ptr); + gnu_cico_list, return_unconstrained_p, + return_by_direct_ref_p, + return_by_invisi_ref_p); /* A subprogram (something that doesn't return anything) shouldn't be considered const since there would be no reason for such a |