summaryrefslogtreecommitdiff
path: root/gcc/ada/gcc-interface
diff options
context:
space:
mode:
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>2012-05-06 10:51:37 +0000
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>2012-05-06 10:51:37 +0000
commit7e48d3e686ad76457648061de51cbb577f965b1b (patch)
tree345b95ed0fb536f8c5e13f0ab85a186a804b2c71 /gcc/ada/gcc-interface
parentcd3ef82256a52fafeafc953d6bdee221b249f0d1 (diff)
downloadgcc-7e48d3e686ad76457648061de51cbb577f965b1b.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@187208 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ada/gcc-interface')
-rw-r--r--gcc/ada/gcc-interface/trans.c259
1 files changed, 149 insertions, 110 deletions
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index fb4a2cd5ffe..c4b9a7e2e31 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -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: