aboutsummaryrefslogtreecommitdiff
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.c339
1 files changed, 67 insertions, 272 deletions
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index 1c26c35..1b7d861 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -285,8 +285,7 @@ gigi (Node_Id gnat_root,
{
Node_Id gnat_iter;
Entity_Id gnat_literal;
- tree long_long_float_type, exception_type, t, ftype;
- tree int64_type = gnat_type_for_size (64, 0);
+ tree t, ftype, int64_type;
struct elab_info *info;
int i;
@@ -304,10 +303,6 @@ gigi (Node_Id gnat_root,
type_annotate_only = (gigi_operating_mode == 1);
-#if TARGET_ABI_OPEN_VMS
- vms_float_format = Float_Format;
-#endif
-
for (i = 0; i < number_file; i++)
{
/* Use the identifier table to make a permanent copy of the filename as
@@ -412,14 +407,6 @@ gigi (Node_Id gnat_root,
NULL, Empty);
DECL_IS_MALLOC (malloc_decl) = 1;
- /* malloc32 is a function declaration tree for a function to allocate
- 32-bit memory on a 64-bit system. Needed only on 64-bit VMS. */
- malloc32_decl
- = create_subprog_decl (get_identifier ("__gnat_malloc32"), NULL_TREE,
- ftype, NULL_TREE, is_disabled, true, true, true,
- NULL, Empty);
- DECL_IS_MALLOC (malloc32_decl) = 1;
-
/* free is a function declaration tree for a function to free memory. */
free_decl
= create_subprog_decl (get_identifier ("__gnat_free"), NULL_TREE,
@@ -430,6 +417,7 @@ gigi (Node_Id gnat_root,
Empty);
/* This is used for 64-bit multiplication with overflow checking. */
+ int64_type = gnat_type_for_size (64, 0);
mulv64_decl
= create_subprog_decl (get_identifier ("__gnat_mulv64"), NULL_TREE,
build_function_type_list (int64_type, int64_type,
@@ -557,9 +545,7 @@ gigi (Node_Id gnat_root,
}
/* Set the types that GCC and Gigi use from the front end. */
- exception_type
- = gnat_to_gnu_entity (Base_Type (standard_exception_type), NULL_TREE, 0);
- except_type_node = TREE_TYPE (exception_type);
+ except_type_node = gnat_to_gnu_type (Base_Type (standard_exception_type));
/* Make other functions used for exception processing. */
get_excptr_decl
@@ -624,21 +610,8 @@ gigi (Node_Id gnat_root,
null_fdesc_node = gnat_build_constructor (fdesc_type_node, null_vec);
}
- long_long_float_type
- = gnat_to_gnu_entity (Base_Type (standard_long_long_float), NULL_TREE, 0);
-
- if (TREE_CODE (TREE_TYPE (long_long_float_type)) == INTEGER_TYPE)
- {
- /* In this case, the builtin floating point types are VAX float,
- so make up a type for use. */
- longest_float_type_node = make_node (REAL_TYPE);
- TYPE_PRECISION (longest_float_type_node) = LONG_DOUBLE_TYPE_SIZE;
- layout_type (longest_float_type_node);
- record_builtin_type ("longest float type", longest_float_type_node,
- false);
- }
- else
- longest_float_type_node = TREE_TYPE (long_long_float_type);
+ longest_float_type_node
+ = get_unpadded_type (Base_Type (standard_long_long_float));
/* Dummy objects to materialize "others" and "all others" in the exception
tables. These are exported by a-exexpr-gcc.adb, so see this unit for
@@ -1497,6 +1470,38 @@ Pragma_to_gnu (Node_Id gnat_node)
return gnu_result;
}
+/* Return an expression for the length of TYPE, an integral type, computed in
+ RESULT_TYPE, another integral type.
+
+ We used to compute the length as MAX (hb - lb + 1, 0) which could overflow
+ when lb == TYPE'First. We now compute it as (hb >= lb) ? hb - lb + 1 : 0
+ which would only overflow in much rarer cases, for extremely large arrays
+ we expect never to encounter in practice. Besides, the former computation
+ required the use of potentially constraining signed arithmetics while the
+ latter does not. Note that the comparison must be done in the original
+ base index type in order to avoid any overflow during the conversion. */
+
+static tree
+get_type_length (tree type, tree result_type)
+{
+ tree comp_type = get_base_type (result_type);
+ tree base_type = get_base_type (type);
+ tree lb = convert (base_type, TYPE_MIN_VALUE (type));
+ tree hb = convert (base_type, TYPE_MAX_VALUE (type));
+ tree length
+ = build_binary_op (PLUS_EXPR, comp_type,
+ build_binary_op (MINUS_EXPR, comp_type,
+ convert (comp_type, hb),
+ convert (comp_type, lb)),
+ convert (comp_type, integer_one_node));
+ length
+ = build_cond_expr (result_type,
+ build_binary_op (GE_EXPR, boolean_type_node, hb, lb),
+ convert (result_type, length),
+ convert (result_type, integer_zero_node));
+ return length;
+}
+
/* Subroutine of gnat_to_gnu to translate GNAT_NODE, an N_Attribute node,
to a GCC tree, which is returned. GNU_RESULT_TYPE_P is a pointer to
where we should place the result type. ATTRIBUTE is the attribute ID. */
@@ -1886,20 +1891,7 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
else if (attribute == Attr_Last)
gnu_result = TYPE_MAX_VALUE (gnu_type);
else
- gnu_result
- = build_binary_op
- (MAX_EXPR, get_base_type (gnu_result_type),
- build_binary_op
- (PLUS_EXPR, get_base_type (gnu_result_type),
- build_binary_op (MINUS_EXPR,
- get_base_type (gnu_result_type),
- convert (gnu_result_type,
- TYPE_MAX_VALUE (gnu_type)),
- convert (gnu_result_type,
- TYPE_MIN_VALUE (gnu_type))),
- convert (gnu_result_type, integer_one_node)),
- convert (gnu_result_type, integer_zero_node));
-
+ gnu_result = get_type_length (gnu_type, gnu_result_type);
break;
}
@@ -2031,37 +2023,10 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
gnu_result = pa->length;
break;
}
- else
- {
- /* We used to compute the length as max (hb - lb + 1, 0),
- which could overflow for some cases of empty arrays, e.g.
- when lb == index_type'first. We now compute the length as
- (hb >= lb) ? hb - lb + 1 : 0, which would only overflow in
- much rarer cases, for extremely large arrays we expect
- never to encounter in practice. In addition, the former
- computation required the use of potentially constraining
- signed arithmetic while the latter doesn't. Note that
- the comparison must be done in the original index type,
- to avoid any overflow during the conversion. */
- tree comp_type = get_base_type (gnu_result_type);
- tree index_type = TYPE_INDEX_TYPE (TYPE_DOMAIN (gnu_type));
- tree lb = TYPE_MIN_VALUE (index_type);
- tree hb = TYPE_MAX_VALUE (index_type);
- gnu_result
- = build_binary_op (PLUS_EXPR, comp_type,
- build_binary_op (MINUS_EXPR,
- comp_type,
- convert (comp_type, hb),
- convert (comp_type, lb)),
- convert (comp_type, integer_one_node));
- gnu_result
- = build_cond_expr (comp_type,
- build_binary_op (GE_EXPR,
- boolean_type_node,
- hb, lb),
- gnu_result,
- convert (comp_type, integer_zero_node));
- }
+
+ gnu_result
+ = get_type_length (TYPE_INDEX_TYPE (TYPE_DOMAIN (gnu_type)),
+ gnu_result_type);
}
/* If this has a PLACEHOLDER_EXPR, qualify it by the object we are
@@ -2334,14 +2299,16 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
case Attr_Machine:
/* The trick is to force the compiler to store the result in memory so
that we do not have extra precision used. But do this only when this
- is necessary, i.e. for a type that is not the longest floating-point
- type and if FP_ARITH_MAY_WIDEN is true. */
+ is necessary, i.e. if FP_ARITH_MAY_WIDEN is true and the precision of
+ the type is lower than that of the longest floating-point type. */
prefix_unused = true;
gnu_expr = gnat_to_gnu (First (Expressions (gnat_node)));
gnu_result_type = get_unpadded_type (Etype (gnat_node));
gnu_result = convert (gnu_result_type, gnu_expr);
- if (gnu_result_type != longest_float_type_node && fp_arith_may_widen)
+ if (fp_arith_may_widen
+ && TYPE_PRECISION (gnu_result_type)
+ < TYPE_PRECISION (longest_float_type_node))
{
tree rec_type = make_node (RECORD_TYPE);
tree field
@@ -2677,8 +2644,8 @@ Loop_Statement_to_gnu (Node_Id gnat_node)
enum tree_code update_code, test_code, shift_code;
bool reverse = Reverse_Present (gnat_loop_spec), use_iv = false;
- gnu_low = TYPE_MIN_VALUE (gnu_type);
- gnu_high = TYPE_MAX_VALUE (gnu_type);
+ gnu_low = convert (gnu_base_type, TYPE_MIN_VALUE (gnu_type));
+ gnu_high = convert (gnu_base_type, TYPE_MAX_VALUE (gnu_type));
/* We must disable modulo reduction for the iteration variable, if any,
in order for the loop comparison to be effective. */
@@ -2971,61 +2938,6 @@ Loop_Statement_to_gnu (Node_Id gnat_node)
return gnu_result;
}
-/* Emit statements to establish __gnat_handle_vms_condition as a VMS condition
- handler for the current function. */
-
-/* This is implemented by issuing a call to the appropriate VMS specific
- builtin. To avoid having VMS specific sections in the global gigi decls
- array, we maintain the decls of interest here. We can't declare them
- inside the function because we must mark them never to be GC'd, which we
- can only do at the global level. */
-
-static GTY(()) tree vms_builtin_establish_handler_decl = NULL_TREE;
-static GTY(()) tree gnat_vms_condition_handler_decl = NULL_TREE;
-
-static void
-establish_gnat_vms_condition_handler (void)
-{
- tree establish_stmt;
-
- /* Elaborate the required decls on the first call. Check on the decl for
- the gnat condition handler to decide, as this is one we create so we are
- sure that it will be non null on subsequent calls. The builtin decl is
- looked up so remains null on targets where it is not implemented yet. */
- if (gnat_vms_condition_handler_decl == NULL_TREE)
- {
- vms_builtin_establish_handler_decl
- = builtin_decl_for
- (get_identifier ("__builtin_establish_vms_condition_handler"));
-
- gnat_vms_condition_handler_decl
- = create_subprog_decl (get_identifier ("__gnat_handle_vms_condition"),
- NULL_TREE,
- build_function_type_list (boolean_type_node,
- ptr_void_type_node,
- ptr_void_type_node,
- NULL_TREE),
- NULL_TREE, is_disabled, true, true, true, NULL,
- Empty);
-
- /* ??? DECL_CONTEXT shouldn't have been set because of DECL_EXTERNAL. */
- DECL_CONTEXT (gnat_vms_condition_handler_decl) = NULL_TREE;
- }
-
- /* Do nothing if the establish builtin is not available, which might happen
- on targets where the facility is not implemented. */
- if (vms_builtin_establish_handler_decl == NULL_TREE)
- return;
-
- establish_stmt
- = build_call_n_expr (vms_builtin_establish_handler_decl, 1,
- build_unary_op
- (ADDR_EXPR, NULL_TREE,
- gnat_vms_condition_handler_decl));
-
- add_stmt (establish_stmt);
-}
-
/* This page implements a form of Named Return Value optimization modelled
on the C++ optimization of the same name. The main difference is that
we disregard any semantical considerations when applying it here, the
@@ -3519,69 +3431,6 @@ build_return_expr (tree ret_obj, tree ret_val)
return build1 (RETURN_EXPR, void_type_node, result_expr);
}
-
-/* Build a stub for the subprogram specified by the GCC tree GNU_SUBPROG
- and the GNAT node GNAT_SUBPROG. */
-
-static void
-build_function_stub (tree gnu_subprog, Entity_Id gnat_subprog)
-{
- tree gnu_subprog_type, gnu_subprog_addr, gnu_subprog_call;
- tree gnu_subprog_param, gnu_stub_param, gnu_param;
- tree gnu_stub_decl = DECL_FUNCTION_STUB (gnu_subprog);
- vec<tree, va_gc> *gnu_param_vec = NULL;
-
- gnu_subprog_type = TREE_TYPE (gnu_subprog);
-
- /* Initialize the information structure for the function. */
- allocate_struct_function (gnu_stub_decl, false);
- set_cfun (NULL);
-
- begin_subprog_body (gnu_stub_decl);
-
- start_stmt_group ();
- gnat_pushlevel ();
-
- /* Loop over the parameters of the stub and translate any of them
- passed by descriptor into a by reference one. */
- for (gnu_stub_param = DECL_ARGUMENTS (gnu_stub_decl),
- gnu_subprog_param = DECL_ARGUMENTS (gnu_subprog);
- gnu_stub_param;
- gnu_stub_param = DECL_CHAIN (gnu_stub_param),
- gnu_subprog_param = DECL_CHAIN (gnu_subprog_param))
- {
- if (DECL_BY_DESCRIPTOR_P (gnu_stub_param))
- {
- gcc_assert (DECL_BY_REF_P (gnu_subprog_param));
- gnu_param
- = convert_vms_descriptor (TREE_TYPE (gnu_subprog_param),
- gnu_stub_param,
- DECL_PARM_ALT_TYPE (gnu_stub_param),
- gnat_subprog);
- }
- else
- gnu_param = gnu_stub_param;
-
- vec_safe_push (gnu_param_vec, gnu_param);
- }
-
- /* Invoke the internal subprogram. */
- gnu_subprog_addr = build1 (ADDR_EXPR, build_pointer_type (gnu_subprog_type),
- gnu_subprog);
- gnu_subprog_call = build_call_vec (TREE_TYPE (gnu_subprog_type),
- gnu_subprog_addr, gnu_param_vec);
-
- /* Propagate the return value, if any. */
- if (VOID_TYPE_P (TREE_TYPE (gnu_subprog_type)))
- add_stmt (gnu_subprog_call);
- else
- add_stmt (build_return_expr (DECL_RESULT (gnu_stub_decl),
- gnu_subprog_call));
-
- gnat_poplevel ();
- end_subprog_body (end_stmt_group ());
- rest_of_subprog_body_compilation (gnu_stub_decl);
-}
/* Subroutine of gnat_to_gnu to process gnat_node, an N_Subprogram_Body. We
don't return anything. */
@@ -3730,22 +3579,6 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
start_stmt_group ();
gnat_pushlevel ();
- /* On VMS, establish our condition handler to possibly turn a condition into
- the corresponding exception if the subprogram has a foreign convention or
- is exported.
-
- To ensure proper execution of local finalizations on condition instances,
- we must turn a condition into the corresponding exception even if there
- is no applicable Ada handler, and need at least one condition handler per
- possible call chain involving GNAT code. OTOH, establishing the handler
- has a cost so we want to minimize the number of subprograms into which
- this happens. The foreign or exported condition is expected to satisfy
- all the constraints. */
- if (TARGET_ABI_OPEN_VMS
- && (Has_Foreign_Convention (gnat_subprog_id)
- || Is_Exported (gnat_subprog_id)))
- establish_gnat_vms_condition_handler ();
-
process_decls (Declarations (gnat_node), Empty, Empty, true, true);
/* Generate the code of the subprogram itself. A return statement will be
@@ -3878,10 +3711,6 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
}
rest_of_subprog_body_compilation (gnu_subprog_decl);
-
- /* If there is a stub associated with the function, build it now. */
- if (DECL_FUNCTION_STUB (gnu_subprog_decl))
- build_function_stub (gnu_subprog_decl, gnat_subprog_id);
}
/* Return true if GNAT_NODE requires atomic synchronization. */
@@ -4091,10 +3920,9 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
const bool is_true_formal_parm
= gnu_formal && TREE_CODE (gnu_formal) == PARM_DECL;
const bool is_by_ref_formal_parm
- = is_true_formal_parm
- && (DECL_BY_REF_P (gnu_formal)
- || DECL_BY_COMPONENT_PTR_P (gnu_formal)
- || DECL_BY_DESCRIPTOR_P (gnu_formal));
+ = is_true_formal_parm
+ && (DECL_BY_REF_P (gnu_formal)
+ || DECL_BY_COMPONENT_PTR_P (gnu_formal));
/* In the Out or In Out case, we must suppress conversions that yield
an lvalue but can nevertheless cause the creation of a temporary,
because we need the real object in this case, either to pass its
@@ -4351,24 +4179,6 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
gnu_actual = build_unary_op (ADDR_EXPR, gnu_formal_type, gnu_actual);
}
- /* Then see if the parameter is passed by descriptor. */
- else if (is_true_formal_parm && DECL_BY_DESCRIPTOR_P (gnu_formal))
- {
- gnu_actual = convert (gnu_formal_type, gnu_actual);
-
- /* If this is 'Null_Parameter, pass a zero descriptor. */
- if ((TREE_CODE (gnu_actual) == INDIRECT_REF
- || TREE_CODE (gnu_actual) == UNCONSTRAINED_ARRAY_REF)
- && TREE_PRIVATE (gnu_actual))
- gnu_actual
- = convert (DECL_ARG_TYPE (gnu_formal), integer_zero_node);
- else
- gnu_actual = build_unary_op (ADDR_EXPR, NULL_TREE,
- fill_vms_descriptor
- (TREE_TYPE (TREE_TYPE (gnu_formal)),
- gnu_actual, gnat_actual));
- }
-
/* Otherwise the parameter is passed by copy. */
else
{
@@ -4482,10 +4292,7 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
if (!(present_gnu_tree (gnat_formal)
&& TREE_CODE (get_gnu_tree (gnat_formal)) == PARM_DECL
&& (DECL_BY_REF_P (get_gnu_tree (gnat_formal))
- || (TREE_CODE (get_gnu_tree (gnat_formal)) == PARM_DECL
- && ((DECL_BY_COMPONENT_PTR_P (get_gnu_tree (gnat_formal))
- || (DECL_BY_DESCRIPTOR_P
- (get_gnu_tree (gnat_formal))))))))
+ || DECL_BY_COMPONENT_PTR_P (get_gnu_tree (gnat_formal))))
&& Ekind (gnat_formal) != E_In_Parameter)
{
/* Get the value to assign to this Out or In Out parameter. It is
@@ -4986,9 +4793,6 @@ Exception_Handler_to_gnu_zcx (Node_Id gnat_node)
gnu_expr = gnat_to_gnu_entity (gnat_ex_id, NULL_TREE, 0);
gnu_etype = build_unary_op (ADDR_EXPR, NULL_TREE, gnu_expr);
-
- /* The Non_Ada_Error case for VMS exceptions is handled
- by the personality routine. */
}
else
gcc_unreachable ();
@@ -5943,25 +5747,16 @@ gnat_to_gnu (Node_Id gnat_node)
case N_Selected_Component:
{
- tree gnu_prefix = gnat_to_gnu (Prefix (gnat_node));
+ Entity_Id gnat_prefix = Prefix (gnat_node);
Entity_Id gnat_field = Entity (Selector_Name (gnat_node));
- Entity_Id gnat_pref_type = Etype (Prefix (gnat_node));
+ tree gnu_prefix = gnat_to_gnu (gnat_prefix);
tree gnu_field;
- while (IN (Ekind (gnat_pref_type), Incomplete_Or_Private_Kind)
- || IN (Ekind (gnat_pref_type), Access_Kind))
- {
- if (IN (Ekind (gnat_pref_type), Incomplete_Or_Private_Kind))
- gnat_pref_type = Underlying_Type (gnat_pref_type);
- else if (IN (Ekind (gnat_pref_type), Access_Kind))
- gnat_pref_type = Designated_Type (gnat_pref_type);
- }
-
gnu_prefix = maybe_implicit_deref (gnu_prefix);
/* For discriminant references in tagged types always substitute the
corresponding discriminant as the actual selected component. */
- if (Is_Tagged_Type (gnat_pref_type))
+ if (Is_Tagged_Type (Etype (gnat_prefix)))
while (Present (Corresponding_Discriminant (gnat_field)))
gnat_field = Corresponding_Discriminant (gnat_field);
@@ -6170,9 +5965,12 @@ gnat_to_gnu (Node_Id gnat_node)
|| Nkind (gnat_range) == N_Expanded_Name)
{
tree gnu_range_type = get_unpadded_type (Entity (gnat_range));
+ tree gnu_range_base_type = get_base_type (gnu_range_type);
- gnu_low = TYPE_MIN_VALUE (gnu_range_type);
- gnu_high = TYPE_MAX_VALUE (gnu_range_type);
+ gnu_low
+ = convert (gnu_range_base_type, TYPE_MIN_VALUE (gnu_range_type));
+ gnu_high
+ = convert (gnu_range_base_type, TYPE_MAX_VALUE (gnu_range_type));
}
else
gcc_unreachable ();
@@ -8625,11 +8423,12 @@ convert_with_check (Entity_Id gnat_type, tree gnu_expr, bool overflowp,
tree gnu_base_type = get_base_type (gnu_type);
tree gnu_result = gnu_expr;
- /* If we are not doing any checks, the output is an integral type, and
- the input is not a floating type, just do the conversion. This
- shortcut is required to avoid problems with packed array types
- and simplifies code in all cases anyway. */
- if (!rangep && !overflowp && INTEGRAL_TYPE_P (gnu_base_type)
+ /* If we are not doing any checks, the output is an integral type and the
+ input is not a floating-point type, just do the conversion. This is
+ required for packed array types and is simpler in all cases anyway. */
+ if (!rangep
+ && !overflowp
+ && INTEGRAL_TYPE_P (gnu_base_type)
&& !FLOAT_TYPE_P (gnu_in_type))
return convert (gnu_type, gnu_expr);
@@ -8730,10 +8529,6 @@ convert_with_check (Entity_Id gnat_type, tree gnu_expr, bool overflowp,
calc_type
= fp_arith_may_widen ? longest_float_type_node : gnu_in_basetype;
- /* FIXME: Should not have padding in the first place. */
- if (TYPE_IS_PADDING_P (calc_type))
- calc_type = TREE_TYPE (TYPE_FIELDS (calc_type));
-
/* Compute the exact value calc_type'Pred (0.5) at compile time. */
fmt = REAL_MODE_FORMAT (TYPE_MODE (calc_type));
real_2expN (&half_minus_pred_half, -(fmt->p) - 1, TYPE_MODE (calc_type));