Commit 55ba23c4 by Eric Botcazou Committed by Eric Botcazou

trans.c (call_to_gnu): In the return-by-target-ptr case do not set the result type if...

	* gcc-interface/trans.c (call_to_gnu): In the return-by-target-ptr case
	do not set the result type if there is a specified target and do not
	convert the result in any cases.
	(protect_multiple_eval): Make direct SAVE_EXPR for CALL_EXPR.
	(maybe_stabilize_reference) <COMPOUND_EXPR>: Merge with CALL_EXPR.

From-SVN: r158053
parent 6392bea6
2010-04-07 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/trans.c (call_to_gnu): In the return-by-target-ptr case
do not set the result type if there is a specified target and do not
convert the result in any cases.
(protect_multiple_eval): Make direct SAVE_EXPR for CALL_EXPR.
(maybe_stabilize_reference) <COMPOUND_EXPR>: Merge with CALL_EXPR.
2010-03-10 Eric Botcazou <ebotcazou@adacore.com> 2010-03-10 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/Makefile.in (SPARC/Solaris): Use sparcv8plus. * gcc-interface/Makefile.in (SPARC/Solaris): Use sparcv8plus.
......
...@@ -2464,6 +2464,8 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target) ...@@ -2464,6 +2464,8 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
= create_var_decl (create_tmp_var_name ("LR"), NULL, gnu_obj_type, = create_var_decl (create_tmp_var_name ("LR"), NULL, gnu_obj_type,
NULL, false, false, false, false, NULL, NULL, false, false, false, false, NULL,
gnat_node); gnat_node);
*gnu_result_type_p = gnu_ret_type;
} }
gnu_actual_list gnu_actual_list
...@@ -2788,38 +2790,19 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target) ...@@ -2788,38 +2790,19 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
the call should be emitted or not. */ the call should be emitted or not. */
if (TYPE_RETURNS_BY_TARGET_PTR_P (gnu_subprog_type)) if (TYPE_RETURNS_BY_TARGET_PTR_P (gnu_subprog_type))
{ {
/* Conceptually, what we need is a COMPOUND_EXPR with the call followed /* Conceptually, what we need is a COMPOUND_EXPR of the call followed by
by the target object converted to the proper type. Doing so would the target object. Doing so would potentially be inefficient though,
potentially be very inefficient, however, as this expression might as this expression might be wrapped up into a SAVE_EXPR later, which
end up wrapped into an outer SAVE_EXPR later on, which would incur a would incur a pointless temporary copy of the whole object.
pointless temporary copy of the whole object.
What we do instead is build a COMPOUND_EXPR returning the address of What we do instead is build a COMPOUND_EXPR returning the address of
the target, and then dereference. Wrapping the COMPOUND_EXPR into a the target, and then dereference. Wrapping up the COMPOUND_EXPR into
SAVE_EXPR later on then only incurs a pointer copy. */ a SAVE_EXPR then only incurs a mere pointer copy. */
tree gnu_target_addr = build_unary_op (ADDR_EXPR, NULL_TREE, gnu_target);
tree gnu_result_type set_expr_location_from_node (gnu_target_addr, gnat_node);
= TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (gnu_subprog_type))); gnu_result = build2 (COMPOUND_EXPR, TREE_TYPE (gnu_target_addr),
gnu_subprog_call, gnu_target_addr);
/* Build and return return build_unary_op (INDIRECT_REF, NULL_TREE, gnu_result);
(result_type) *[gnu_subprog_call (&gnu_target, ...), &gnu_target] */
tree gnu_target_address
= build_unary_op (ADDR_EXPR, NULL_TREE, gnu_target);
set_expr_location_from_node (gnu_target_address, gnat_node);
gnu_result
= build2 (COMPOUND_EXPR, TREE_TYPE (gnu_target_address),
gnu_subprog_call, gnu_target_address);
gnu_result
= unchecked_convert (gnu_result_type,
build_unary_op (INDIRECT_REF, NULL_TREE,
gnu_result),
false);
*gnu_result_type_p = gnu_result_type;
return gnu_result;
} }
/* If it is a function call, the result is the call expression unless /* If it is a function call, the result is the call expression unless
...@@ -7321,12 +7304,16 @@ protect_multiple_eval (tree exp) ...@@ -7321,12 +7304,16 @@ protect_multiple_eval (tree exp)
return build1 (TREE_CODE (exp), type, return build1 (TREE_CODE (exp), type,
protect_multiple_eval (TREE_OPERAND (exp, 0))); protect_multiple_eval (TREE_OPERAND (exp, 0)));
/* If this is a fat pointer or something that can be placed into a /* If this is a fat pointer or something that can be placed in a register,
register, just make a SAVE_EXPR. */ just make a SAVE_EXPR. Likewise for a CALL_EXPR as large objects are
if (TYPE_IS_FAT_POINTER_P (type) || TYPE_MODE (type) != BLKmode) returned via invisible reference in most ABIs so the temporary will
directly be filled by the callee. */
if (TYPE_IS_FAT_POINTER_P (type)
|| TYPE_MODE (type) != BLKmode
|| TREE_CODE (exp) == CALL_EXPR)
return save_expr (exp); return save_expr (exp);
/* Otherwise, reference, protect the address and dereference. */ /* Otherwise reference, protect the address and dereference. */
return return
build_unary_op (INDIRECT_REF, type, build_unary_op (INDIRECT_REF, type,
save_expr (build_unary_op (ADDR_EXPR, save_expr (build_unary_op (ADDR_EXPR,
...@@ -7403,14 +7390,8 @@ maybe_stabilize_reference (tree ref, bool force, bool *success) ...@@ -7403,14 +7390,8 @@ maybe_stabilize_reference (tree ref, bool force, bool *success)
NULL_TREE, NULL_TREE); NULL_TREE, NULL_TREE);
break; break;
case COMPOUND_EXPR:
result = gnat_stabilize_reference_1 (ref, force);
break;
case CALL_EXPR: case CALL_EXPR:
/* This generates better code than the scheme in protect_multiple_eval case COMPOUND_EXPR:
because large objects will be returned via invisible reference in
most ABIs so the temporary will directly be filled by the callee. */
result = gnat_stabilize_reference_1 (ref, force); result = gnat_stabilize_reference_1 (ref, force);
break; break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment