mirror of git://gcc.gnu.org/git/gcc.git
trans.c (Loop_Statement_to_gnu): Also handle invariant conditions with only one bound.
* gcc-interface/trans.c (Loop_Statement_to_gnu): Also handle invariant conditions with only one bound. (Raise_Error_to_gnu): Likewise. New function extracted from... (gnat_to_gnu) <N_Raise_Constraint_Error>: ...here. Call above function in regular mode only. From-SVN: r187208
This commit is contained in:
parent
1a5b6cd2af
commit
8009661301
|
@ -1,3 +1,11 @@
|
|||
2012-05-06 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
* gcc-interface/trans.c (Loop_Statement_to_gnu): Also handle invariant
|
||||
conditions with only one bound.
|
||||
(Raise_Error_to_gnu): Likewise. New function extracted from...
|
||||
(gnat_to_gnu) <N_Raise_Constraint_Error>: ...here. Call above function
|
||||
in regular mode only.
|
||||
|
||||
2012-05-06 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
* gcc-interface/misc.c (gnat_post_options): Disable caret by default.
|
||||
|
|
|
@ -2563,13 +2563,19 @@ Loop_Statement_to_gnu (Node_Id gnat_node)
|
|||
i++)
|
||||
{
|
||||
tree low_ok
|
||||
= build_binary_op (GE_EXPR, boolean_type_node,
|
||||
convert (rci->type, gnu_low),
|
||||
rci->low_bound);
|
||||
= rci->low_bound
|
||||
? build_binary_op (GE_EXPR, boolean_type_node,
|
||||
convert (rci->type, gnu_low),
|
||||
rci->low_bound)
|
||||
: boolean_true_node;
|
||||
|
||||
tree high_ok
|
||||
= build_binary_op (LE_EXPR, boolean_type_node,
|
||||
convert (rci->type, gnu_high),
|
||||
rci->high_bound);
|
||||
= rci->high_bound
|
||||
? build_binary_op (LE_EXPR, boolean_type_node,
|
||||
convert (rci->type, gnu_high),
|
||||
rci->high_bound)
|
||||
: boolean_true_node;
|
||||
|
||||
tree range_ok
|
||||
= build_binary_op (TRUTH_ANDIF_EXPR, boolean_type_node,
|
||||
low_ok, high_ok);
|
||||
|
@ -2794,7 +2800,7 @@ finalize_nrv_r (tree *tp, int *walk_subtrees, void *data)
|
|||
tree ret_val = TREE_OPERAND (TREE_OPERAND (t, 0), 1), init_expr;
|
||||
|
||||
/* If this is the temporary created for a return value with variable
|
||||
size in call_to_gnu, we replace the RHS with the init expression. */
|
||||
size in Call_to_gnu, we replace the RHS with the init expression. */
|
||||
if (TREE_CODE (ret_val) == COMPOUND_EXPR
|
||||
&& TREE_CODE (TREE_OPERAND (ret_val, 0)) == INIT_EXPR
|
||||
&& TREE_OPERAND (TREE_OPERAND (ret_val, 0), 0)
|
||||
|
@ -3122,7 +3128,7 @@ build_return_expr (tree ret_obj, tree ret_val)
|
|||
&& aggregate_value_p (operation_type, current_function_decl))
|
||||
{
|
||||
/* Recognize the temporary created for a return value with variable
|
||||
size in call_to_gnu. We want to eliminate it if possible. */
|
||||
size in Call_to_gnu. We want to eliminate it if possible. */
|
||||
if (TREE_CODE (ret_val) == COMPOUND_EXPR
|
||||
&& TREE_CODE (TREE_OPERAND (ret_val, 0)) == INIT_EXPR
|
||||
&& TREE_OPERAND (TREE_OPERAND (ret_val, 0), 0)
|
||||
|
@ -3583,7 +3589,7 @@ create_init_temporary (const char *prefix, tree gnu_init, tree *gnu_init_stmt,
|
|||
requires atomic synchronization. */
|
||||
|
||||
static tree
|
||||
call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
|
||||
Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
|
||||
bool atomic_sync)
|
||||
{
|
||||
const bool function_call = (Nkind (gnat_node) == N_Function_Call);
|
||||
|
@ -4751,6 +4757,134 @@ Compilation_Unit_to_gnu (Node_Id gnat_node)
|
|||
invalidate_global_renaming_pointers ();
|
||||
}
|
||||
|
||||
/* Subroutine of gnat_to_gnu to translate gnat_node, an N_Raise_xxx_Error,
|
||||
to a GCC tree, which is returned. GNU_RESULT_TYPE_P is a pointer to where
|
||||
we should place the result type. LABEL_P is true if there is a label to
|
||||
branch to for the exception. */
|
||||
|
||||
static tree
|
||||
Raise_Error_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
|
||||
{
|
||||
const Node_Kind kind = Nkind (gnat_node);
|
||||
const int reason = UI_To_Int (Reason (gnat_node));
|
||||
const Node_Id gnat_cond = Condition (gnat_node);
|
||||
const bool with_extra_info
|
||||
= Exception_Extra_Info
|
||||
&& !No_Exception_Handlers_Set ()
|
||||
&& !get_exception_label (kind);
|
||||
tree gnu_result = NULL_TREE, gnu_cond = NULL_TREE;
|
||||
|
||||
*gnu_result_type_p = get_unpadded_type (Etype (gnat_node));
|
||||
|
||||
switch (reason)
|
||||
{
|
||||
case CE_Access_Check_Failed:
|
||||
if (with_extra_info)
|
||||
gnu_result = build_call_raise_column (reason, gnat_node);
|
||||
break;
|
||||
|
||||
case CE_Index_Check_Failed:
|
||||
case CE_Range_Check_Failed:
|
||||
case CE_Invalid_Data:
|
||||
if (Present (gnat_cond) && Nkind (gnat_cond) == N_Op_Not)
|
||||
{
|
||||
Node_Id gnat_range, gnat_index, gnat_type;
|
||||
tree gnu_index, gnu_low_bound, gnu_high_bound;
|
||||
struct range_check_info_d *rci;
|
||||
|
||||
switch (Nkind (Right_Opnd (gnat_cond)))
|
||||
{
|
||||
case N_In:
|
||||
gnat_range = Right_Opnd (Right_Opnd (gnat_cond));
|
||||
gcc_assert (Nkind (gnat_range) == N_Range);
|
||||
gnu_low_bound = gnat_to_gnu (Low_Bound (gnat_range));
|
||||
gnu_high_bound = gnat_to_gnu (High_Bound (gnat_range));
|
||||
break;
|
||||
|
||||
case N_Op_Ge:
|
||||
gnu_low_bound = gnat_to_gnu (Right_Opnd (Right_Opnd (gnat_cond)));
|
||||
gnu_high_bound = NULL_TREE;
|
||||
break;
|
||||
|
||||
case N_Op_Le:
|
||||
gnu_low_bound = NULL_TREE;
|
||||
gnu_high_bound = gnat_to_gnu (Right_Opnd (Right_Opnd (gnat_cond)));
|
||||
break;
|
||||
|
||||
default:
|
||||
goto common;
|
||||
}
|
||||
|
||||
gnat_index = Left_Opnd (Right_Opnd (gnat_cond));
|
||||
gnat_type = Etype (gnat_index);
|
||||
gnu_index = gnat_to_gnu (gnat_index);
|
||||
|
||||
if (with_extra_info
|
||||
&& gnu_low_bound
|
||||
&& gnu_high_bound
|
||||
&& Known_Esize (gnat_type)
|
||||
&& UI_To_Int (Esize (gnat_type)) <= 32)
|
||||
gnu_result
|
||||
= build_call_raise_range (reason, gnat_node, gnu_index,
|
||||
gnu_low_bound, gnu_high_bound);
|
||||
|
||||
/* If loop unswitching is enabled, we try to compute invariant
|
||||
conditions for checks applied to iteration variables, i.e.
|
||||
conditions that are both independent of the variable and
|
||||
necessary in order for the check to fail in the course of
|
||||
some iteration, and prepend them to the original condition
|
||||
of the checks. This will make it possible later for the
|
||||
loop unswitching pass to replace the loop with two loops,
|
||||
one of which has the checks eliminated and the other has
|
||||
the original checks reinstated, and a run time selection.
|
||||
The former loop will be suitable for vectorization. */
|
||||
if (flag_unswitch_loops
|
||||
&& (!gnu_low_bound
|
||||
|| (gnu_low_bound = gnat_invariant_expr (gnu_low_bound)))
|
||||
&& (!gnu_high_bound
|
||||
|| (gnu_high_bound = gnat_invariant_expr (gnu_high_bound)))
|
||||
&& (rci = push_range_check_info (gnu_index)))
|
||||
{
|
||||
rci->low_bound = gnu_low_bound;
|
||||
rci->high_bound = gnu_high_bound;
|
||||
rci->type = gnat_to_gnu_type (gnat_type);
|
||||
rci->invariant_cond = build1 (SAVE_EXPR, boolean_type_node,
|
||||
boolean_true_node);
|
||||
gnu_cond = build_binary_op (TRUTH_ANDIF_EXPR,
|
||||
boolean_type_node,
|
||||
rci->invariant_cond,
|
||||
gnat_to_gnu (gnat_cond));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
common:
|
||||
if (!gnu_result)
|
||||
gnu_result = build_call_raise (reason, gnat_node, kind);
|
||||
set_expr_location_from_node (gnu_result, gnat_node);
|
||||
|
||||
/* If the type is VOID, this is a statement, so we need to generate the code
|
||||
for the call. Handle a condition, if there is one. */
|
||||
if (VOID_TYPE_P (*gnu_result_type_p))
|
||||
{
|
||||
if (Present (gnat_cond))
|
||||
{
|
||||
if (!gnu_cond)
|
||||
gnu_cond = gnat_to_gnu (gnat_cond);
|
||||
gnu_result = build3 (COND_EXPR, void_type_node, gnu_cond, gnu_result,
|
||||
alloc_stmt_list ());
|
||||
}
|
||||
}
|
||||
else
|
||||
gnu_result = build1 (NULL_EXPR, *gnu_result_type_p, gnu_result);
|
||||
|
||||
return gnu_result;
|
||||
}
|
||||
|
||||
/* Return true if GNAT_NODE is on the LHS of an assignment or an actual
|
||||
parameter of a call. */
|
||||
|
||||
|
@ -5949,7 +6083,7 @@ gnat_to_gnu (Node_Id gnat_node)
|
|||
N_Raise_Storage_Error);
|
||||
else if (Nkind (Expression (gnat_node)) == N_Function_Call)
|
||||
gnu_result
|
||||
= call_to_gnu (Expression (gnat_node), &gnu_result_type, gnu_lhs,
|
||||
= Call_to_gnu (Expression (gnat_node), &gnu_result_type, gnu_lhs,
|
||||
atomic_sync_required_p (Name (gnat_node)));
|
||||
else
|
||||
{
|
||||
|
@ -6238,7 +6372,7 @@ gnat_to_gnu (Node_Id gnat_node)
|
|||
|
||||
case N_Function_Call:
|
||||
case N_Procedure_Call_Statement:
|
||||
gnu_result = call_to_gnu (gnat_node, &gnu_result_type, NULL_TREE, false);
|
||||
gnu_result = Call_to_gnu (gnat_node, &gnu_result_type, NULL_TREE, false);
|
||||
break;
|
||||
|
||||
/************************/
|
||||
|
@ -6661,105 +6795,10 @@ gnat_to_gnu (Node_Id gnat_node)
|
|||
case N_Raise_Constraint_Error:
|
||||
case N_Raise_Program_Error:
|
||||
case N_Raise_Storage_Error:
|
||||
{
|
||||
const int reason = UI_To_Int (Reason (gnat_node));
|
||||
const Node_Id gnat_cond = Condition (gnat_node);
|
||||
const bool with_extra_info = Exception_Extra_Info
|
||||
&& !No_Exception_Handlers_Set ()
|
||||
&& !get_exception_label (kind);
|
||||
tree gnu_cond = NULL_TREE;
|
||||
|
||||
if (type_annotate_only)
|
||||
{
|
||||
gnu_result = alloc_stmt_list ();
|
||||
break;
|
||||
}
|
||||
|
||||
gnu_result_type = get_unpadded_type (Etype (gnat_node));
|
||||
|
||||
switch (reason)
|
||||
{
|
||||
case CE_Access_Check_Failed:
|
||||
if (with_extra_info)
|
||||
gnu_result = build_call_raise_column (reason, gnat_node);
|
||||
break;
|
||||
|
||||
case CE_Index_Check_Failed:
|
||||
case CE_Range_Check_Failed:
|
||||
case CE_Invalid_Data:
|
||||
if (Present (gnat_cond)
|
||||
&& Nkind (gnat_cond) == N_Op_Not
|
||||
&& Nkind (Right_Opnd (gnat_cond)) == N_In
|
||||
&& Nkind (Right_Opnd (Right_Opnd (gnat_cond))) == N_Range)
|
||||
{
|
||||
Node_Id gnat_index = Left_Opnd (Right_Opnd (gnat_cond));
|
||||
Node_Id gnat_type = Etype (gnat_index);
|
||||
Node_Id gnat_range = Right_Opnd (Right_Opnd (gnat_cond));
|
||||
tree gnu_index = gnat_to_gnu (gnat_index);
|
||||
tree gnu_low_bound = gnat_to_gnu (Low_Bound (gnat_range));
|
||||
tree gnu_high_bound = gnat_to_gnu (High_Bound (gnat_range));
|
||||
struct range_check_info_d *rci;
|
||||
|
||||
if (with_extra_info
|
||||
&& Known_Esize (gnat_type)
|
||||
&& UI_To_Int (Esize (gnat_type)) <= 32)
|
||||
gnu_result
|
||||
= build_call_raise_range (reason, gnat_node, gnu_index,
|
||||
gnu_low_bound, gnu_high_bound);
|
||||
|
||||
/* If loop unswitching is enabled, we try to compute invariant
|
||||
conditions for checks applied to iteration variables, i.e.
|
||||
conditions that are both independent of the variable and
|
||||
necessary in order for the check to fail in the course of
|
||||
some iteration, and prepend them to the original condition
|
||||
of the checks. This will make it possible later for the
|
||||
loop unswitching pass to replace the loop with two loops,
|
||||
one of which has the checks eliminated and the other has
|
||||
the original checks reinstated, and a run time selection.
|
||||
The former loop will be suitable for vectorization. */
|
||||
if (flag_unswitch_loops
|
||||
&& (gnu_low_bound = gnat_invariant_expr (gnu_low_bound))
|
||||
&& (gnu_high_bound = gnat_invariant_expr (gnu_high_bound))
|
||||
&& (rci = push_range_check_info (gnu_index)))
|
||||
{
|
||||
rci->low_bound = gnu_low_bound;
|
||||
rci->high_bound = gnu_high_bound;
|
||||
rci->type = gnat_to_gnu_type (gnat_type);
|
||||
rci->invariant_cond = build1 (SAVE_EXPR, boolean_type_node,
|
||||
boolean_true_node);
|
||||
gnu_cond = build_binary_op (TRUTH_ANDIF_EXPR,
|
||||
boolean_type_node,
|
||||
rci->invariant_cond,
|
||||
gnat_to_gnu (gnat_cond));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (gnu_result == error_mark_node)
|
||||
gnu_result = build_call_raise (reason, gnat_node, kind);
|
||||
|
||||
set_expr_location_from_node (gnu_result, gnat_node);
|
||||
|
||||
/* If the type is VOID, this is a statement, so we need to generate
|
||||
the code for the call. Handle a condition, if there is one. */
|
||||
if (VOID_TYPE_P (gnu_result_type))
|
||||
{
|
||||
if (Present (gnat_cond))
|
||||
{
|
||||
if (!gnu_cond)
|
||||
gnu_cond = gnat_to_gnu (gnat_cond);
|
||||
gnu_result
|
||||
= build3 (COND_EXPR, void_type_node, gnu_cond, gnu_result,
|
||||
alloc_stmt_list ());
|
||||
}
|
||||
}
|
||||
else
|
||||
gnu_result = build1 (NULL_EXPR, gnu_result_type, gnu_result);
|
||||
}
|
||||
if (type_annotate_only)
|
||||
gnu_result = alloc_stmt_list ();
|
||||
else
|
||||
gnu_result = Raise_Error_to_gnu (gnat_node, &gnu_result_type);
|
||||
break;
|
||||
|
||||
case N_Validate_Unchecked_Conversion:
|
||||
|
|
Loading…
Reference in New Issue