diff options
author | Richard Kenner <kenner@vlsi1.ultra.nyu.edu> | 2006-02-15 10:31:40 +0100 |
---|---|---|
committer | Arnaud Charlet <charlet@gcc.gnu.org> | 2006-02-15 10:31:40 +0100 |
commit | 5b47742c2d278f8f8a4b1e02c6e1f786340da38f (patch) | |
tree | 1fd44711246a1ea895cf60b81987968b22bb417e /gcc/ada/trans.c | |
parent | 0022d9e31d01f2a31808ff38f66dd3e3ac96927a (diff) | |
download | gcc-5b47742c2d278f8f8a4b1e02c6e1f786340da38f.zip gcc-5b47742c2d278f8f8a4b1e02c6e1f786340da38f.tar.gz gcc-5b47742c2d278f8f8a4b1e02c6e1f786340da38f.tar.bz2 |
re PR ada/26096 (Ada bootstrap fails in g-alleve.adb)
2006-02-13 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
Olivier Hainque <hainque@adacore.com>
Eric Botcazou <ebotcazou@adacore.com>
* ada-tree.h: (TYPE_UNCHECKED_UNION_P): Deleted.
* gigi.h (value_factor_p): Add prototype and description, now public.
* decl.c (gnat_to_gnu_field): Don't attempt BLKmode to integral type
promotion for field with rep clause if the associated size was proven
to be in error.
Expand comments describing attempts to use a packable type.
(gnat_to_gnu_entity) <E_Signed_Integer_Subtype,
E_Floating_Point_Subtype>: Inherit alias set of what we are making a
subtype of to ensure conflicts amongst all subtypes in a hierarchy,
necessary since these are not different types and pointers may
actually designate any subtype in this hierarchy.
(gnat_to_gnu_entity, case E_Record_Type): Always make fields for
discriminants but put them into record only if not Unchecked_Union;
pass flag to components_to_record showing Unchecked_Union.
(make_dummy_type): Use UNION_TYPE only if Unchecked_Union and no
components before variants; don't set TYPE_UNCHECKED_UNION_P.
(components_to_record): New argument UNCHECKED_UNION.
Remove special case code for Unchecked_Union and instead use main code
with small changes.
PR ada/26096
(gnat_to_gnu_entity) <E_Variable>: Do not initialize the
aligning variable with the expression being built, only its inner
field.
* trans.c (Handled_Sequence_Of_Statements_to_gnu): Remove call to
emit_sequence_entry_statements.
(emit_sequence_entry_statements, body_with_handlers_p): Delete.
(establish_gnat_vms_condition_handler): Move before
Subprogram_Body_to_gnu.
(Subprogram_Body_to_gnu): On VMS, establish_gnat_vms_condition_handler
for a subprogram if it has a foreign convention or is exported.
(Identifier_to_gnu): Manually unshare the DECL_INITIAL tree when it is
substituted for a CONST_DECL.
(tree_transform, case N_Aggregate): Remove code for UNION_TYPE and pass
Etype to assoc_to_constructor.
(assoc_to_constructor): New argument, GNAT_ENTITY; use it to ignore
discriminants of Unchecked_Union.
(TARGET_ABI_OPEN_VMS): Define to 0 if not defined, so that later uses
don't need cluttering preprocessor directives.
(establish_gnat_vms_condition_handler): New function. Establish the GNAT
condition handler as current in the compiled function.
(body_with_handlers_p): New function. Tell whether a given sequence of
statements node is attached to a package or subprogram body and involves
exception handlers possibly nested within inner block statements.
(emit_sequence_entry_statements): New function, to emit special
statements on entry of sequences when necessary. Establish GNAT
condition handler in the proper cases for VMS.
(Handled_Sequence_Of_Statements_to_gnu): Start block code with
emit_sequence_entry_statements.
* utils2.c (find_common_type): If both input types are BLKmode and
have a constant size, use the smaller one.
(build_simple_component_ref): Also match if FIELD and NEW_FIELD are
the same.
* utils.c (value_factor_p): Make public, to allow uses from other gigi
units.
(create_type_decl): Do not set the flag DECL_IGNORED_P for dummy types.
(convert, case UNION_TYPE): Remove special treatment for unchecked
unions.
PR ada/18659
(update_pointer_to): Update variants of pointer types to
unconstrained arrays by attaching the list of fields of the main
variant.
From-SVN: r111030
Diffstat (limited to 'gcc/ada/trans.c')
-rw-r--r-- | gcc/ada/trans.c | 123 |
1 files changed, 100 insertions, 23 deletions
diff --git a/gcc/ada/trans.c b/gcc/ada/trans.c index f8698c5..1a9f3f4 100644 --- a/gcc/ada/trans.c +++ b/gcc/ada/trans.c @@ -6,7 +6,7 @@ * * * C Implementation File * * * - * Copyright (C) 1992-2005, Free Software Foundation, Inc. * + * Copyright (C) 1992-2006, Free Software Foundation, Inc. * * * * GNAT is free software; you can redistribute it and/or modify it under * * terms of the GNU General Public License as published by the Free Soft- * @@ -57,6 +57,12 @@ #include "ada-tree.h" #include "gigi.h" +/* Let code below know whether we are targetting VMS without need of + intrusive preprocessor directives. */ +#ifndef TARGET_ABI_OPEN_VMS +#define TARGET_ABI_OPEN_VMS 0 +#endif + int max_gnat_nodes; int number_names; struct Node *Nodes_Ptr; @@ -159,7 +165,7 @@ static tree emit_index_check (tree, tree, tree, tree); static tree emit_check (tree, tree, int); static tree convert_with_check (Entity_Id, tree, bool, bool, bool); static bool addressable_p (tree); -static tree assoc_to_constructor (Node_Id, tree); +static tree assoc_to_constructor (Entity_Id, Node_Id, tree); static tree extract_values (tree, tree); static tree pos_to_constructor (Node_Id, tree, Entity_Id); static tree maybe_implicit_deref (tree); @@ -446,7 +452,18 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p) == Attr_Unchecked_Access) || (Get_Attribute_Id (Attribute_Name (gnat_temp)) == Attr_Unrestricted_Access))))) - gnu_result = DECL_INITIAL (gnu_result); + { + gnu_result = DECL_INITIAL (gnu_result); + /* ??? The mark/unmark mechanism implemented in Gigi to prevent tree + sharing between global level and subprogram level doesn't apply + to elaboration routines. As a result, the DECL_INITIAL tree may + be shared between the static initializer of a global object and + the elaboration routine, thus wreaking havoc if a local temporary + is created in place during gimplification of the latter and the + former is emitted afterwards. Manually unshare for now. */ + if (TREE_VISITED (gnu_result)) + gnu_result = unshare_expr (gnu_result); + } } *gnu_result_type_p = gnu_result_type; @@ -1340,6 +1357,57 @@ 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 (integer_type_node, + ptr_void_type_node, + ptr_void_type_node, + NULL_TREE), + NULL_TREE, 0, 1, 1, 0, Empty); + } + + /* 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_1_expr (vms_builtin_establish_handler_decl, + build_unary_op + (ADDR_EXPR, NULL_TREE, + gnat_vms_condition_handler_decl)); + + add_stmt (establish_stmt); +} + /* Subroutine of gnat_to_gnu to process gnat_node, an N_Subprogram_Body. We don't return anything. */ @@ -1433,6 +1501,22 @@ Subprogram_Body_to_gnu (Node_Id gnat_node) gnat_to_gnu_entity (gnat_param, NULL_TREE, 1)); } + + /* 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 mimize 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_node) || Is_Exported (gnat_node))) + 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 @@ -3082,25 +3166,11 @@ gnat_to_gnu (Node_Id gnat_node) if (Null_Record_Present (gnat_node)) gnu_result = gnat_build_constructor (gnu_aggr_type, NULL_TREE); - else if (TREE_CODE (gnu_aggr_type) == UNION_TYPE - && TYPE_UNCHECKED_UNION_P (gnu_aggr_type)) - { - /* The first element is the discrimant, which we ignore. The - next is the field we're building. Convert the expression - to the type of the field and then to the union type. */ - Node_Id gnat_assoc - = Next (First (Component_Associations (gnat_node))); - Entity_Id gnat_field = Entity (First (Choices (gnat_assoc))); - tree gnu_field_type - = TREE_TYPE (gnat_to_gnu_entity (gnat_field, NULL_TREE, 0)); - - gnu_result = convert (gnu_field_type, - gnat_to_gnu (Expression (gnat_assoc))); - } else if (TREE_CODE (gnu_aggr_type) == RECORD_TYPE || TREE_CODE (gnu_aggr_type) == UNION_TYPE) gnu_result - = assoc_to_constructor (First (Component_Associations (gnat_node)), + = assoc_to_constructor (Etype (gnat_node), + First (Component_Associations (gnat_node)), gnu_aggr_type); else if (TREE_CODE (gnu_aggr_type) == ARRAY_TYPE) gnu_result = pos_to_constructor (First (Expressions (gnat_node)), @@ -3996,7 +4066,8 @@ gnat_to_gnu (Node_Id gnat_node) if (Present (Actual_Designated_Subtype (gnat_node))) { - gnu_actual_obj_type = gnat_to_gnu_type (Actual_Designated_Subtype (gnat_node)); + gnu_actual_obj_type + = gnat_to_gnu_type (Actual_Designated_Subtype (gnat_node)); if (TYPE_FAT_OR_THIN_POINTER_P (gnu_ptr_type)) gnu_actual_obj_type @@ -5582,13 +5653,14 @@ process_type (Entity_Id gnat_entity) } } -/* GNAT_ASSOC is the front of the Component_Associations of an N_Aggregate. - GNU_TYPE is the GCC type of the corresponding record. +/* GNAT_ENTITY is the type of the resulting constructors, + GNAT_ASSOC is the front of the Component_Associations of an N_Aggregate, + and GNU_TYPE is the GCC type of the corresponding record. Return a CONSTRUCTOR to build the record. */ static tree -assoc_to_constructor (Node_Id gnat_assoc, tree gnu_type) +assoc_to_constructor (Entity_Id gnat_entity, Node_Id gnat_assoc, tree gnu_type) { tree gnu_list, gnu_result; @@ -5614,6 +5686,11 @@ assoc_to_constructor (Node_Id gnat_assoc, tree gnu_type) && Is_Tagged_Type (Scope (Entity (gnat_field)))) continue; + /* Also ignore discriminants of Unchecked_Unions. */ + else if (Is_Unchecked_Union (gnat_entity) + && Ekind (Entity (gnat_field)) == E_Discriminant) + continue; + /* Before assigning a value in an aggregate make sure range checks are done if required. Then convert to the type of the field. */ if (Do_Range_Check (Expression (gnat_assoc))) |