aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/gcc-interface/decl.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/gcc-interface/decl.c')
-rw-r--r--gcc/ada/gcc-interface/decl.c30
1 files changed, 25 insertions, 5 deletions
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index 0669875..98ca932 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -972,7 +972,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
save_gnu_tree (gnat_entity, gnu_decl, true);
saved = true;
annotate_object (gnat_entity, gnu_type, NULL_TREE,
- false);
+ false, false);
break;
}
@@ -1471,7 +1471,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
type of the object and not on the object directly, and makes it
possible to support all confirming representation clauses. */
annotate_object (gnat_entity, TREE_TYPE (gnu_decl), gnu_object_size,
- used_by_ref);
+ used_by_ref, false);
}
break;
@@ -5282,7 +5282,8 @@ gnat_to_gnu_param (Entity_Id gnat_param, Mechanism_Type mech,
bool in_param = (Ekind (gnat_param) == E_In_Parameter);
/* The parameter can be indirectly modified if its address is taken. */
bool ro_param = in_param && !Address_Taken (gnat_param);
- bool by_return = false, by_component_ptr = false, by_ref = false;
+ bool by_return = false, by_component_ptr = false;
+ bool by_ref = false, by_double_ref = false;
tree gnu_param;
/* Copy-return is used only for the first parameter of a valued procedure.
@@ -5399,6 +5400,19 @@ gnat_to_gnu_param (Entity_Id gnat_param, Mechanism_Type mech,
{
gnu_param_type = build_reference_type (gnu_param_type);
by_ref = true;
+
+ /* In some ABIs, e.g. SPARC 32-bit, fat pointer types are themselves
+ passed by reference. Pass them by explicit reference, this will
+ generate more debuggable code at -O0. */
+ if (TYPE_IS_FAT_POINTER_P (gnu_param_type)
+ && targetm.calls.pass_by_reference (NULL,
+ TYPE_MODE (gnu_param_type),
+ gnu_param_type,
+ true))
+ {
+ gnu_param_type = build_reference_type (gnu_param_type);
+ by_double_ref = true;
+ }
}
/* Pass In Out or Out parameters using copy-in copy-out mechanism. */
@@ -5441,6 +5455,7 @@ gnat_to_gnu_param (Entity_Id gnat_param, Mechanism_Type mech,
gnu_param = create_param_decl (gnu_param_name, gnu_param_type,
ro_param || by_ref || by_component_ptr);
DECL_BY_REF_P (gnu_param) = by_ref;
+ DECL_BY_DOUBLE_REF_P (gnu_param) = by_double_ref;
DECL_BY_COMPONENT_PTR_P (gnu_param) = by_component_ptr;
DECL_BY_DESCRIPTOR_P (gnu_param) = (mech == By_Descriptor ||
mech == By_Short_Descriptor);
@@ -7397,13 +7412,18 @@ annotate_value (tree gnu_size)
/* Given GNAT_ENTITY, an object (constant, variable, parameter, exception)
and GNU_TYPE, its corresponding GCC type, set Esize and Alignment to the
size and alignment used by Gigi. Prefer SIZE over TYPE_SIZE if non-null.
- BY_REF is true if the object is used by reference. */
+ BY_REF is true if the object is used by reference and BY_DOUBLE_REF is
+ true if the object is used by double reference. */
void
-annotate_object (Entity_Id gnat_entity, tree gnu_type, tree size, bool by_ref)
+annotate_object (Entity_Id gnat_entity, tree gnu_type, tree size, bool by_ref,
+ bool by_double_ref)
{
if (by_ref)
{
+ if (by_double_ref)
+ gnu_type = TREE_TYPE (gnu_type);
+
if (TYPE_IS_FAT_POINTER_P (gnu_type))
gnu_type = TYPE_UNCONSTRAINED_ARRAY (gnu_type);
else