summaryrefslogtreecommitdiff
path: root/gcc/ada/gcc-interface/trans.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/gcc-interface/trans.c')
-rw-r--r--gcc/ada/gcc-interface/trans.c155
1 files changed, 125 insertions, 30 deletions
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index 4a4d0faa9f6..3482d2ce39b 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -353,6 +353,7 @@ gigi (Node_Id gnat_root,
/* Initialize ourselves. */
init_code_table ();
+ init_gnat_decl ();
init_gnat_utils ();
/* If we are just annotating types, give VOID_TYPE zero sizes to avoid
@@ -727,6 +728,7 @@ gigi (Node_Id gnat_root,
}
/* Destroy ourselves. */
+ destroy_gnat_decl ();
destroy_gnat_utils ();
/* We cannot track the location of errors past this point. */
@@ -896,17 +898,8 @@ lvalue_required_p (Node_Id gnat_node, tree gnu_type, bool constant,
address_of_constant, aliased);
case N_Object_Renaming_Declaration:
- /* We need to make a real renaming only if the constant object is
- aliased or if we may use a renaming pointer; otherwise we can
- optimize and return the rvalue. We make an exception if the object
- is an identifier since in this case the rvalue can be propagated
- attached to the CONST_DECL. */
- return (!constant
- || aliased
- /* This should match the constant case of the renaming code. */
- || Is_Composite_Type
- (Underlying_Type (Etype (Name (gnat_parent))))
- || Nkind (Name (gnat_parent)) == N_Identifier);
+ /* We need to preserve addresses through a renaming. */
+ return 1;
case N_Object_Declaration:
/* We cannot use a constructor if this is an atomic object because
@@ -966,6 +959,77 @@ lvalue_required_p (Node_Id gnat_node, tree gnu_type, bool constant,
gcc_unreachable ();
}
+/* Return true if T is a constant DECL node that can be safely replaced
+ by its initializer. */
+
+static bool
+constant_decl_with_initializer_p (tree t)
+{
+ if (!TREE_CONSTANT (t) || !DECL_P (t) || !DECL_INITIAL (t))
+ return false;
+
+ /* Return false for aggregate types that contain a placeholder since
+ their initializers cannot be manipulated easily. */
+ if (AGGREGATE_TYPE_P (TREE_TYPE (t))
+ && !TYPE_IS_FAT_POINTER_P (TREE_TYPE (t))
+ && type_contains_placeholder_p (TREE_TYPE (t)))
+ return false;
+
+ return true;
+}
+
+/* Return an expression equivalent to EXP but where constant DECL nodes
+ have been replaced by their initializer. */
+
+static tree
+fold_constant_decl_in_expr (tree exp)
+{
+ enum tree_code code = TREE_CODE (exp);
+ tree op0;
+
+ switch (code)
+ {
+ case CONST_DECL:
+ case VAR_DECL:
+ if (!constant_decl_with_initializer_p (exp))
+ return exp;
+
+ return DECL_INITIAL (exp);
+
+ case BIT_FIELD_REF:
+ case COMPONENT_REF:
+ op0 = fold_constant_decl_in_expr (TREE_OPERAND (exp, 0));
+ if (op0 == TREE_OPERAND (exp, 0))
+ return exp;
+
+ return fold_build3 (code, TREE_TYPE (exp), op0, TREE_OPERAND (exp, 1),
+ TREE_OPERAND (exp, 2));
+
+ case ARRAY_REF:
+ case ARRAY_RANGE_REF:
+ op0 = fold_constant_decl_in_expr (TREE_OPERAND (exp, 0));
+ if (op0 == TREE_OPERAND (exp, 0))
+ return exp;
+
+ return fold (build4 (code, TREE_TYPE (exp), op0, TREE_OPERAND (exp, 1),
+ TREE_OPERAND (exp, 2), TREE_OPERAND (exp, 3)));
+
+ case VIEW_CONVERT_EXPR:
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
+ op0 = fold_constant_decl_in_expr (TREE_OPERAND (exp, 0));
+ if (op0 == TREE_OPERAND (exp, 0))
+ return exp;
+
+ return fold_build1 (code, TREE_TYPE (exp), op0);
+
+ default:
+ return exp;
+ }
+
+ gcc_unreachable ();
+}
+
/* Subroutine of gnat_to_gnu to translate gnat_node, an N_Identifier,
to a GCC tree, which is returned. GNU_RESULT_TYPE_P is a pointer
to where we should place the result type. */
@@ -1110,13 +1174,16 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
true, false)))
gnu_result = DECL_INITIAL (gnu_result);
- /* If it's a renaming pointer and we are at the right binding level,
- we can reference the renamed object directly, since the renamed
- expression has been protected against multiple evaluations. */
+ /* If it's a renaming pointer and, either the renamed object is constant
+ or we are at the right binding level, we can reference the renamed
+ object directly, since it is constant or has been protected against
+ multiple evaluations. */
if (TREE_CODE (gnu_result) == VAR_DECL
&& !DECL_LOOP_PARM_P (gnu_result)
&& DECL_RENAMED_OBJECT (gnu_result)
- && (!DECL_RENAMING_GLOBAL_P (gnu_result) || global_bindings_p ()))
+ && (TREE_CONSTANT (DECL_RENAMED_OBJECT (gnu_result))
+ || !DECL_RENAMING_GLOBAL_P (gnu_result)
+ || global_bindings_p ()))
gnu_result = DECL_RENAMED_OBJECT (gnu_result);
/* Otherwise, do the final dereference. */
@@ -1136,15 +1203,8 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
/* If we have a constant declaration and its initializer, try to return the
latter to avoid the need to call fold in lots of places and the need for
- elaboration code if this identifier is used as an initializer itself.
- Don't do it for aggregate types that contain a placeholder since their
- initializers cannot be manipulated easily. */
- if (TREE_CONSTANT (gnu_result)
- && DECL_P (gnu_result)
- && DECL_INITIAL (gnu_result)
- && !(AGGREGATE_TYPE_P (TREE_TYPE (gnu_result))
- && !TYPE_IS_FAT_POINTER_P (TREE_TYPE (gnu_result))
- && type_contains_placeholder_p (TREE_TYPE (gnu_result))))
+ elaboration code if this identifier is used as an initializer itself. */
+ if (constant_decl_with_initializer_p (gnu_result))
{
bool constant_only = (TREE_CODE (gnu_result) == CONST_DECL
&& !DECL_CONST_CORRESPONDING_VAR (gnu_result));
@@ -1164,6 +1224,21 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
gnu_result = DECL_INITIAL (gnu_result);
}
+ /* But for a constant renaming we couldn't do that incrementally for its
+ definition because of the need to return an lvalue so, if the present
+ context doesn't itself require an lvalue, we try again here. */
+ else if (Ekind (gnat_temp) == E_Constant
+ && Is_Elementary_Type (gnat_temp_type)
+ && Present (Renamed_Object (gnat_temp)))
+ {
+ if (require_lvalue < 0)
+ require_lvalue
+ = lvalue_required_p (gnat_node, gnu_result_type, true, false,
+ Is_Aliased (gnat_temp));
+ if (!require_lvalue)
+ gnu_result = fold_constant_decl_in_expr (gnu_result);
+ }
+
/* The GNAT tree has the type of a function set to its result type, so we
adjust here. Also use the type of the result if the Etype is a subtype
that is nominally unconstrained. Likewise if this is a deferred constant
@@ -1266,10 +1341,14 @@ Pragma_to_gnu (Node_Id gnat_node)
Present (gnat_temp);
gnat_temp = Next (gnat_temp))
{
- tree gnu_loop_stmt = gnu_loop_stack ->last ()->stmt;
+ tree gnu_loop_stmt = gnu_loop_stack->last ()->stmt;
switch (Chars (Expression (gnat_temp)))
{
+ case Name_Ivdep:
+ LOOP_STMT_IVDEP (gnu_loop_stmt) = 1;
+ break;
+
case Name_No_Unroll:
LOOP_STMT_NO_UNROLL (gnu_loop_stmt) = 1;
break;
@@ -7745,13 +7824,29 @@ gnat_gimplify_stmt (tree *stmt_p)
tree gnu_cond = LOOP_STMT_COND (stmt);
tree gnu_update = LOOP_STMT_UPDATE (stmt);
tree gnu_end_label = LOOP_STMT_LABEL (stmt);
- tree t;
/* Build the condition expression from the test, if any. */
if (gnu_cond)
- gnu_cond
- = build3 (COND_EXPR, void_type_node, gnu_cond, alloc_stmt_list (),
- build1 (GOTO_EXPR, void_type_node, gnu_end_label));
+ {
+ /* Deal with the optimization hints. */
+ if (LOOP_STMT_IVDEP (stmt))
+ gnu_cond = build2 (ANNOTATE_EXPR, TREE_TYPE (gnu_cond), gnu_cond,
+ build_int_cst (integer_type_node,
+ annot_expr_ivdep_kind));
+
+ if (LOOP_STMT_NO_VECTOR (stmt))
+ gnu_cond = build2 (ANNOTATE_EXPR, TREE_TYPE (gnu_cond), gnu_cond,
+ build_int_cst (integer_type_node,
+ annot_expr_no_vector_kind));
+ if (LOOP_STMT_VECTOR (stmt))
+ gnu_cond = build2 (ANNOTATE_EXPR, TREE_TYPE (gnu_cond), gnu_cond,
+ build_int_cst (integer_type_node,
+ annot_expr_vector_kind));
+
+ gnu_cond
+ = build3 (COND_EXPR, void_type_node, gnu_cond, NULL_TREE,
+ build1 (GOTO_EXPR, void_type_node, gnu_end_label));
+ }
/* Set to emit the statements of the loop. */
*stmt_p = NULL_TREE;
@@ -7780,7 +7875,7 @@ gnat_gimplify_stmt (tree *stmt_p)
if (gnu_update && !LOOP_STMT_TOP_UPDATE_P (stmt))
append_to_statement_list (gnu_update, stmt_p);
- t = build1 (GOTO_EXPR, void_type_node, gnu_start_label);
+ tree t = build1 (GOTO_EXPR, void_type_node, gnu_start_label);
SET_EXPR_LOCATION (t, DECL_SOURCE_LOCATION (gnu_end_label));
append_to_statement_list (t, stmt_p);