From 6155ec0d2fe3e6c144a22b65f8855e17ed92eebe Mon Sep 17 00:00:00 2001 From: ebotcazou Date: Thu, 8 Apr 2010 20:16:36 +0000 Subject: [PATCH] * 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) : 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) : 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) : 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) : New case. (build_return_expr): Adjust parameter names, logic and comment. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@158139 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 10 +++++ gcc/ada/ChangeLog | 38 +++++++++++++++++++ gcc/ada/gcc-interface/trans.c | 87 +++++++++++-------------------------------- gcc/gimplify.c | 62 +++++++++++++++++++++++++++++- 4 files changed, 129 insertions(+), 68 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f676ed481ad..565f8329bae 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2010-04-08 Eric Botcazou + + * 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) : New case. + 2010-04-08 Jing Yu Zdenek Dvorak diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index c740fa82c20..e43a534a792 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,41 @@ +2010-04-08 Eric Botcazou + + * 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) : + 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) : 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) : New case. + (build_return_expr): Adjust parameter names, logic and comment. + 2010-04-07 Eric Botcazou * exp_pakd.adb (Create_Packed_Array_Type): Always use a modular type diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c index 0f4cef001e4..640dab147cf 100644 --- a/gcc/ada/gcc-interface/trans.c +++ b/gcc/ada/gcc-interface/trans.c @@ -2619,8 +2619,9 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target) subprogram. */ tree gnu_subprog = gnat_to_gnu (Name (gnat_node)); /* The FUNCTION_TYPE node giving the GCC type of the subprogram. */ - tree gnu_subprog_type = TREE_TYPE (gnu_subprog); - tree gnu_subprog_addr = build_unary_op (ADDR_EXPR, NULL_TREE, gnu_subprog); + tree gnu_subprog_type = TREE_TYPE (gnu_subprog_node); + tree gnu_subprog_addr + = build_unary_op (ADDR_EXPR, NULL_TREE, gnu_subprog_node); Entity_Id gnat_formal; Node_Id gnat_actual; VEC(tree,gc) *gnu_actual_vec = NULL; @@ -2644,33 +2645,19 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target) gnat_actual = Next_Actual (gnat_actual)) add_stmt (gnat_to_gnu (gnat_actual)); - if (Nkind (gnat_node) == N_Function_Call && !gnu_target) - { - tree gnu_obj_type; - - if (CONTAINS_PLACEHOLDER_P (TYPE_SIZE (gnu_ret_type))) - gnu_obj_type - = maybe_pad_type (gnu_ret_type, - max_size (TYPE_SIZE (gnu_ret_type), true), - 0, Etype (Name (gnat_node)), false, false, - false, true); - else - gnu_obj_type = gnu_ret_type; - - /* ??? We may be about to create a static temporary if we happen to - be at the global binding level. That's a regression from what - the 3.x back-end would generate in the same situation, but we - don't have a mechanism in Gigi for creating automatic variables - in the elaboration routines. */ - gnu_target - = create_var_decl (create_tmp_var_name ("LR"), NULL, gnu_obj_type, - NULL, false, false, false, false, NULL, - gnat_node); - - *gnu_result_type_p = gnu_ret_type; - } + { + tree call_expr + = build_call_raise (PE_Stubbed_Subprogram_Called, gnat_node, + N_Raise_Program_Error); - return call_expr; + if (Nkind (gnat_node) == N_Function_Call && !gnu_target) + { + *gnu_result_type_p = TREE_TYPE (gnu_subprog_type); + return build1 (NULL_EXPR, *gnu_result_type_p, call_expr); + } + else + return call_expr; + } } /* The only way we can be making a call via an access type is if Name is an @@ -3001,33 +2988,13 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target) nreverse (gnu_actual_list)); set_expr_location_from_node (gnu_subprog_call, gnat_node); - /* If we return by passing a target, the result is the target after the - call. We must not emit the call directly here because this might be - evaluated as part of an expression with conditions to control whether - the call should be emitted or not. */ - if (TYPE_RETURNS_BY_TARGET_PTR_P (gnu_subprog_type)) + /* If it's a function call, the result is the call expression unless a target + is specified, in which case we copy the result into the target and return + the assignment statement. */ + if (Nkind (gnat_node) == N_Function_Call) { - /* Conceptually, what we need is a COMPOUND_EXPR of the call followed by - the target object. Doing so would potentially be inefficient though, - as this expression might be wrapped up into a SAVE_EXPR later, which - would incur a pointless temporary copy of the whole object. - - What we do instead is build a COMPOUND_EXPR returning the address of - the target, and then dereference. Wrapping up the COMPOUND_EXPR into - a SAVE_EXPR then only incurs a mere pointer copy. */ - tree gnu_target_addr = build_unary_op (ADDR_EXPR, NULL_TREE, gnu_target); - set_expr_location_from_node (gnu_target_addr, gnat_node); - gnu_result = build2 (COMPOUND_EXPR, TREE_TYPE (gnu_target_addr), - gnu_subprog_call, gnu_target_addr); - return build_unary_op (INDIRECT_REF, NULL_TREE, gnu_result); - } - - /* If it is a function call, the result is the call expression unless - a target is specified, in which case we copy the result into the target - and return the assignment statement. */ - else if (Nkind (gnat_node) == N_Function_Call) - { - tree gnu_result = gnu_call; + gnu_result = gnu_subprog_call; + enum tree_code op_code; /* If the function returns an unconstrained array or by direct reference, we have to dereference the pointer. */ @@ -3037,15 +3004,6 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target) if (gnu_target) { - Node_Id gnat_parent = Parent (gnat_node); - enum tree_code op_code; - - /* If range check is needed, emit code to generate it. */ - if (Do_Range_Check (gnat_node)) - gnu_result - = emit_range_check (gnu_result, Etype (Name (gnat_parent)), - gnat_parent); - /* ??? If the return type has non-constant size, then force the return slot optimization as we would not be able to generate a temporary. That's what has been done historically. */ @@ -3056,9 +3014,6 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target) gnu_result = build_binary_op (op_code, NULL_TREE, gnu_target, gnu_result); - add_stmt_with_node (gnu_result, gnat_parent); - gnat_poplevel (); - gnu_result = end_stmt_group (); } else { diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 2b402720b1a..890ab23139c 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -4308,8 +4308,66 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, } } - default: - break; + ret = GS_UNHANDLED; + break; + + case WITH_SIZE_EXPR: + /* Likewise for calls that return an aggregate of non-constant size, + since we would not be able to generate a temporary at all. */ + if (TREE_CODE (TREE_OPERAND (*from_p, 0)) == CALL_EXPR) + { + *from_p = TREE_OPERAND (*from_p, 0); + ret = GS_OK; + } + else + ret = GS_UNHANDLED; + break; + + /* If we're initializing from a container, push the initialization + inside it. */ + case CLEANUP_POINT_EXPR: + case BIND_EXPR: + case STATEMENT_LIST: + { + tree wrap = *from_p; + tree t; + + ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_min_lval, + fb_lvalue); + if (ret != GS_ERROR) + ret = GS_OK; + + t = voidify_wrapper_expr (wrap, *expr_p); + gcc_assert (t == *expr_p); + + if (want_value) + { + gimplify_and_add (wrap, pre_p); + *expr_p = unshare_expr (*to_p); + } + else + *expr_p = wrap; + return GS_OK; + } + + case COMPOUND_LITERAL_EXPR: + { + tree complit = TREE_OPERAND (*expr_p, 1); + tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (complit); + tree decl = DECL_EXPR_DECL (decl_s); + tree init = DECL_INITIAL (decl); + + /* struct T x = (struct T) { 0, 1, 2 } can be optimized + into struct T x = { 0, 1, 2 } if the address of the + compound literal has never been taken. */ + if (!TREE_ADDRESSABLE (complit) + && !TREE_ADDRESSABLE (decl) + && init) + { + *expr_p = copy_node (*expr_p); + TREE_OPERAND (*expr_p, 1) = init; + return GS_OK; + } } } while (changed); -- 2.11.0