aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/gcc-interface/trans.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/gcc-interface/trans.cc')
-rw-r--r--gcc/ada/gcc-interface/trans.cc79
1 files changed, 55 insertions, 24 deletions
diff --git a/gcc/ada/gcc-interface/trans.cc b/gcc/ada/gcc-interface/trans.cc
index 23fc814..e02804b 100644
--- a/gcc/ada/gcc-interface/trans.cc
+++ b/gcc/ada/gcc-interface/trans.cc
@@ -257,7 +257,7 @@ static tree emit_check (tree, tree, int, Node_Id);
static tree build_unary_op_trapv (enum tree_code, tree, tree, Node_Id);
static tree build_binary_op_trapv (enum tree_code, tree, tree, tree, Node_Id);
static tree convert_with_check (Entity_Id, tree, bool, bool, Node_Id);
-static bool addressable_p (tree, tree);
+static bool addressable_p (tree, tree, bool);
static bool aliasable_p (tree, tree);
static tree assoc_to_constructor (Entity_Id, Node_Id, tree);
static tree pos_to_constructor (Node_Id, tree);
@@ -4876,6 +4876,8 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
tree gnu_formal = present_gnu_tree (gnat_formal)
? get_gnu_tree (gnat_formal) : NULL_TREE;
tree gnu_actual_type = gnat_to_gnu_type (Etype (gnat_actual));
+ const bool is_init_proc
+ = Is_Entity_Name (gnat_subprog) && Is_Init_Proc (Entity (gnat_subprog));
const bool in_param = (Ekind (gnat_formal) == E_In_Parameter);
const bool is_true_formal_parm
= gnu_formal && TREE_CODE (gnu_formal) == PARM_DECL;
@@ -4925,7 +4927,7 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
copy to avoid breaking strict aliasing rules. */
if (is_by_ref_formal_parm
&& (gnu_name_type = gnat_to_gnu_type (Etype (gnat_name)))
- && (!addressable_p (gnu_name, gnu_name_type)
+ && (!addressable_p (gnu_name, gnu_name_type, is_init_proc)
|| (node_is_type_conversion (gnat_actual)
&& (aliasing = !aliasable_p (gnu_name, gnu_actual_type)))))
{
@@ -5051,9 +5053,7 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
/* Do not initialize it for the _Init parameter of an initialization
procedure since no data is meant to be passed in. */
- if (Ekind (gnat_formal) == E_Out_Parameter
- && Is_Entity_Name (gnat_subprog)
- && Is_Init_Proc (Entity (gnat_subprog)))
+ if (Ekind (gnat_formal) == E_Out_Parameter && is_init_proc)
gnu_name = gnu_temp = create_temporary ("A", TREE_TYPE (gnu_name));
/* Initialize it on the fly like for an implicit temporary in the
@@ -7590,6 +7590,10 @@ gnat_to_gnu (Node_Id gnat_node)
case N_Allocator:
{
+ const Entity_Id gnat_desig_type
+ = Designated_Type (Underlying_Type (Etype (gnat_node)));
+ const Entity_Id gnat_pool = Storage_Pool (gnat_node);
+
tree gnu_type, gnu_init;
bool ignore_init_type;
@@ -7608,9 +7612,6 @@ gnat_to_gnu (Node_Id gnat_node)
else if (Nkind (gnat_temp) == N_Qualified_Expression)
{
- const Entity_Id gnat_desig_type
- = Designated_Type (Underlying_Type (Etype (gnat_node)));
-
ignore_init_type = Has_Constrained_Partial_View (gnat_desig_type);
gnu_init = gnat_to_gnu (Expression (gnat_temp));
@@ -7637,11 +7638,24 @@ gnat_to_gnu (Node_Id gnat_node)
else
gcc_unreachable ();
- gnu_result_type = get_unpadded_type (Etype (gnat_node));
+ /* If this is an array allocated with its bounds, use the thin pointer
+ as the result type to trigger the machinery in build_allocator, but
+ make sure not to do it for allocations on the return and secondary
+ stacks (see build_call_alloc_dealloc_proc for more details). */
+ if (Is_Constr_Array_Subt_With_Bounds (gnat_desig_type)
+ && Is_Record_Type (Underlying_Type (Etype (gnat_pool)))
+ && !type_annotate_only)
+ {
+ tree gnu_array = gnat_to_gnu_type (Base_Type (gnat_desig_type));
+ gnu_result_type
+ = build_pointer_type (TYPE_OBJECT_RECORD_TYPE (gnu_array));
+ }
+ else
+ gnu_result_type = get_unpadded_type (Etype (gnat_node));
+
return build_allocator (gnu_type, gnu_init, gnu_result_type,
Procedure_To_Call (gnat_node),
- Storage_Pool (gnat_node), gnat_node,
- ignore_init_type);
+ gnat_pool, gnat_node, ignore_init_type);
}
break;
@@ -8577,6 +8591,18 @@ gnat_to_gnu (Node_Id gnat_node)
(void) gnat_to_gnu_entity (gnat_desig_type, NULL_TREE, false);
gnu_ptr = gnat_to_gnu (gnat_temp);
+
+ /* If this is an array allocated with its bounds, first convert to
+ the thin pointer to trigger the special machinery below. */
+ if (Is_Constr_Array_Subt_With_Bounds (gnat_desig_type))
+ {
+ tree gnu_array = gnat_to_gnu_type (Base_Type (gnat_desig_type));
+ gnu_ptr
+ = convert (build_pointer_type
+ (TYPE_OBJECT_RECORD_TYPE (gnu_array)),
+ gnu_ptr);
+ }
+
gnu_ptr_type = TREE_TYPE (gnu_ptr);
/* If this is a thin pointer, we must first dereference it to create
@@ -10353,7 +10379,8 @@ convert_with_check (Entity_Id gnat_type, tree gnu_expr, bool overflow_p,
unless it is an expression involving computation or if it involves a
reference to a bitfield or to an object not sufficiently aligned for
its type. If GNU_TYPE is non-null, return true only if GNU_EXPR can
- be directly addressed as an object of this type.
+ be directly addressed as an object of this type. COMPG is true when
+ the predicate is invoked for compiler-generated code.
*** Notes on addressability issues in the Ada compiler ***
@@ -10410,7 +10437,7 @@ convert_with_check (Entity_Id gnat_type, tree gnu_expr, bool overflow_p,
generated to connect everything together. */
static bool
-addressable_p (tree gnu_expr, tree gnu_type)
+addressable_p (tree gnu_expr, tree gnu_type, bool compg)
{
/* For an integral type, the size of the actual type of the object may not
be greater than that of the expected type, otherwise an indirect access
@@ -10471,13 +10498,13 @@ addressable_p (tree gnu_expr, tree gnu_type)
case COMPOUND_EXPR:
/* The address of a compound expression is that of its 2nd operand. */
- return addressable_p (TREE_OPERAND (gnu_expr, 1), gnu_type);
+ return addressable_p (TREE_OPERAND (gnu_expr, 1), gnu_type, compg);
case COND_EXPR:
/* We accept &COND_EXPR as soon as both operands are addressable and
expect the outcome to be the address of the selected operand. */
- return (addressable_p (TREE_OPERAND (gnu_expr, 1), NULL_TREE)
- && addressable_p (TREE_OPERAND (gnu_expr, 2), NULL_TREE));
+ return (addressable_p (TREE_OPERAND (gnu_expr, 1), NULL_TREE, compg)
+ && addressable_p (TREE_OPERAND (gnu_expr, 2), NULL_TREE, compg));
case COMPONENT_REF:
return (((!DECL_BIT_FIELD (TREE_OPERAND (gnu_expr, 1))
@@ -10491,23 +10518,26 @@ addressable_p (tree gnu_expr, tree gnu_type)
&& (DECL_ALIGN (TREE_OPERAND (gnu_expr, 1))
>= default_field_alignment (TREE_OPERAND (gnu_expr, 1),
TREE_TYPE (gnu_expr))
- /* We do not enforce this on strict-alignment platforms for
- internal fields in order to keep supporting misalignment
- of tagged types in legacy code. */
+ /* But this was historically not enforced for targets that
+ do not require strict alignment, so we keep not doing
+ it for 1) internal fields in order to keep supporting
+ misalignment of tagged types and 2) compiler-generated
+ code in order to avoid creating useless temporaries. */
|| (!STRICT_ALIGNMENT
- && DECL_INTERNAL_P (TREE_OPERAND (gnu_expr, 1)))))
+ && (DECL_INTERNAL_P (TREE_OPERAND (gnu_expr, 1))
+ || compg))))
/* The field of a padding record is always addressable. */
|| TYPE_IS_PADDING_P (TREE_TYPE (TREE_OPERAND (gnu_expr, 0))))
- && addressable_p (TREE_OPERAND (gnu_expr, 0), NULL_TREE));
+ && addressable_p (TREE_OPERAND (gnu_expr, 0), NULL_TREE, compg));
case ARRAY_REF: case ARRAY_RANGE_REF:
case REALPART_EXPR: case IMAGPART_EXPR:
case NOP_EXPR:
- return addressable_p (TREE_OPERAND (gnu_expr, 0), NULL_TREE);
+ return addressable_p (TREE_OPERAND (gnu_expr, 0), NULL_TREE, compg);
case CONVERT_EXPR:
return (AGGREGATE_TYPE_P (TREE_TYPE (gnu_expr))
- && addressable_p (TREE_OPERAND (gnu_expr, 0), NULL_TREE));
+ && addressable_p (TREE_OPERAND (gnu_expr, 0), NULL_TREE, compg));
case VIEW_CONVERT_EXPR:
{
@@ -10525,7 +10555,8 @@ addressable_p (tree gnu_expr, tree gnu_type)
|| TYPE_ALIGN (inner_type) >= BIGGEST_ALIGNMENT
|| TYPE_ALIGN_OK (type)
|| TYPE_ALIGN_OK (inner_type))))
- && addressable_p (TREE_OPERAND (gnu_expr, 0), NULL_TREE));
+ && addressable_p (TREE_OPERAND (gnu_expr, 0), NULL_TREE,
+ compg));
}
default: