summaryrefslogtreecommitdiff
path: root/gcc/ada/gcc-interface/trans.c
diff options
context:
space:
mode:
authorhjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4>2010-07-01 22:22:57 +0000
committerhjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4>2010-07-01 22:22:57 +0000
commit9e169c4bf36a38689550c059570c57efbf00a6fb (patch)
tree95e6800f7ac2a49ff7f799d96f04172320e70ac0 /gcc/ada/gcc-interface/trans.c
parent6170dfb6edfb7b19f8ae5209b8f948fe0076a4ad (diff)
downloadgcc-vect256.tar.gz
Merged trunk at revision 161680 into branch.vect256
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/vect256@161681 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ada/gcc-interface/trans.c')
-rw-r--r--gcc/ada/gcc-interface/trans.c331
1 files changed, 170 insertions, 161 deletions
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index 1732069b699..46848f230f7 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -153,35 +153,25 @@ struct GTY((chain_next ("%h.next"))) elab_info {
static GTY(()) struct elab_info *elab_info_list;
-/* Free list of TREE_LIST nodes used for stacks. */
-static GTY((deletable)) tree gnu_stack_free_list;
+/* Stack of exception pointer variables. Each entry is the VAR_DECL
+ that stores the address of the raised exception. Nonzero means we
+ are in an exception handler. Not used in the zero-cost case. */
+static GTY(()) VEC(tree,gc) *gnu_except_ptr_stack;
-/* List of TREE_LIST nodes representing a stack of exception pointer
- variables. TREE_VALUE is the VAR_DECL that stores the address of
- the raised exception. Nonzero means we are in an exception
- handler. Not used in the zero-cost case. */
-static GTY(()) tree gnu_except_ptr_stack;
+/* Stack for storing the current elaboration procedure decl. */
+static GTY(()) VEC(tree,gc) *gnu_elab_proc_stack;
-/* List of TREE_LIST nodes used to store the current elaboration procedure
- decl. TREE_VALUE is the decl. */
-static GTY(()) tree gnu_elab_proc_stack;
+/* Stack of labels to be used as a goto target instead of a return in
+ some functions. See processing for N_Subprogram_Body. */
+static GTY(()) VEC(tree,gc) *gnu_return_label_stack;
-/* Variable that stores a list of labels to be used as a goto target instead of
- a return in some functions. See processing for N_Subprogram_Body. */
-static GTY(()) tree gnu_return_label_stack;
+/* Stack of LOOP_STMT nodes. */
+static GTY(()) VEC(tree,gc) *gnu_loop_label_stack;
-/* List of TREE_LIST nodes representing a stack of LOOP_STMT nodes.
- TREE_VALUE of each entry is the label of the corresponding LOOP_STMT. */
-static GTY(()) tree gnu_loop_label_stack;
-
-/* List of TREE_LIST nodes representing labels for switch statements.
- TREE_VALUE of each entry is the label at the end of the switch. */
-static GTY(()) tree gnu_switch_label_stack;
-
-/* List of TREE_LIST nodes containing the stacks for N_{Push,Pop}_*_Label. */
-static GTY(()) tree gnu_constraint_error_label_stack;
-static GTY(()) tree gnu_storage_error_label_stack;
-static GTY(()) tree gnu_program_error_label_stack;
+/* The stacks for N_{Push,Pop}_*_Label. */
+static GTY(()) VEC(tree,gc) *gnu_constraint_error_label_stack;
+static GTY(()) VEC(tree,gc) *gnu_storage_error_label_stack;
+static GTY(()) VEC(tree,gc) *gnu_program_error_label_stack;
/* Map GNAT tree codes to GCC tree codes for simple expressions. */
static enum tree_code gnu_codes[Number_Node_Kinds];
@@ -192,10 +182,8 @@ static void record_code_position (Node_Id);
static void insert_code_for (Node_Id);
static void add_cleanup (tree, Node_Id);
static void add_stmt_list (List_Id);
-static void push_exception_label_stack (tree *, Entity_Id);
+static void push_exception_label_stack (VEC(tree,gc) **, Entity_Id);
static tree build_stmt_group (List_Id, bool);
-static void push_stack (tree *, tree, tree);
-static void pop_stack (tree *);
static enum gimplify_status gnat_gimplify_stmt (tree *);
static void elaborate_all_entities (Node_Id);
static void process_freeze_entity (Node_Id);
@@ -213,6 +201,7 @@ static tree extract_values (tree, tree);
static tree pos_to_constructor (Node_Id, tree, Entity_Id);
static tree maybe_implicit_deref (tree);
static void set_expr_location_from_node (tree, Node_Id);
+static void set_gnu_expr_location_from_node (tree, Node_Id);
static int lvalue_required_p (Node_Id, tree, bool, bool, bool);
/* Hooks for debug info back-ends, only supported and used in a restricted set
@@ -555,10 +544,16 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name ATTRIBUTE_UNUSED,
if (TARGET_VTABLE_USES_DESCRIPTORS)
{
tree null_node = fold_convert (ptr_void_ftype, null_pointer_node);
- tree field_list = NULL_TREE, null_list = NULL_TREE;
+ tree field_list = NULL_TREE;
int j;
+ VEC(constructor_elt,gc) *null_vec = NULL;
+ constructor_elt *elt;
fdesc_type_node = make_node (RECORD_TYPE);
+ VEC_safe_grow (constructor_elt, gc, null_vec,
+ TARGET_VTABLE_USES_DESCRIPTORS);
+ elt = (VEC_address (constructor_elt,null_vec)
+ + TARGET_VTABLE_USES_DESCRIPTORS - 1);
for (j = 0; j < TARGET_VTABLE_USES_DESCRIPTORS; j++)
{
@@ -567,12 +562,14 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name ATTRIBUTE_UNUSED,
NULL_TREE, NULL_TREE, 0, 1);
TREE_CHAIN (field) = field_list;
field_list = field;
- null_list = tree_cons (field, null_node, null_list);
+ elt->index = field;
+ elt->value = null_node;
+ elt--;
}
finish_record_type (fdesc_type_node, nreverse (field_list), 0, false);
record_builtin_type ("descriptor", fdesc_type_node);
- null_fdesc_node = gnat_build_constructor (fdesc_type_node, null_list);
+ null_fdesc_node = gnat_build_constructor (fdesc_type_node, null_vec);
}
long_long_float_type
@@ -609,11 +606,10 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name ATTRIBUTE_UNUSED,
user available facilities for Intrinsic imports. */
gnat_install_builtins ();
- gnu_except_ptr_stack = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE);
- gnu_constraint_error_label_stack
- = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE);
- gnu_storage_error_label_stack = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE);
- gnu_program_error_label_stack = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE);
+ VEC_safe_push (tree, gc, gnu_except_ptr_stack, NULL_TREE);
+ VEC_safe_push (tree, gc, gnu_constraint_error_label_stack, NULL_TREE);
+ VEC_safe_push (tree, gc, gnu_storage_error_label_stack, NULL_TREE);
+ VEC_safe_push (tree, gc, gnu_program_error_label_stack, NULL_TREE);
/* Process any Pragma Ident for the main unit. */
#ifdef ASM_OUTPUT_IDENT
@@ -973,7 +969,7 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
variables of non-constant size because they are automatically allocated
to memory. There might be no way of allocating a proper temporary for
them in any case. We only do this for SJLJ though. */
- if (TREE_VALUE (gnu_except_ptr_stack)
+ if (VEC_last (tree, gnu_except_ptr_stack)
&& TREE_CODE (gnu_result) == VAR_DECL
&& TREE_CODE (DECL_SIZE_UNIT (gnu_result)) == INTEGER_CST)
TREE_THIS_VOLATILE (gnu_result) = TREE_SIDE_EFFECTS (gnu_result) = 1;
@@ -1242,10 +1238,12 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
else if (TARGET_VTABLE_USES_DESCRIPTORS
&& Is_Dispatch_Table_Entity (Etype (gnat_node)))
{
- tree gnu_field, gnu_list = NULL_TREE, t;
+ tree gnu_field, t;
/* Descriptors can only be built here for top-level functions. */
bool build_descriptor = (global_bindings_p () != 0);
int i;
+ VEC(constructor_elt,gc) *gnu_vec = NULL;
+ constructor_elt *elt;
gnu_result_type = get_unpadded_type (Etype (gnat_node));
@@ -1260,6 +1258,10 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
gnu_result = build1 (INDIRECT_REF, gnu_result_type, gnu_result);
}
+ VEC_safe_grow (constructor_elt, gc, gnu_vec,
+ TARGET_VTABLE_USES_DESCRIPTORS);
+ elt = (VEC_address (constructor_elt, gnu_vec)
+ + TARGET_VTABLE_USES_DESCRIPTORS - 1);
for (gnu_field = TYPE_FIELDS (gnu_result_type), i = 0;
i < TARGET_VTABLE_USES_DESCRIPTORS;
gnu_field = TREE_CHAIN (gnu_field), i++)
@@ -1274,10 +1276,12 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
t = build3 (COMPONENT_REF, ptr_void_ftype, gnu_result,
gnu_field, NULL_TREE);
- gnu_list = tree_cons (gnu_field, t, gnu_list);
+ elt->index = gnu_field;
+ elt->value = t;
+ elt--;
}
- gnu_result = gnat_build_constructor (gnu_result_type, gnu_list);
+ gnu_result = gnat_build_constructor (gnu_result_type, gnu_vec);
break;
}
@@ -1605,7 +1609,7 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
if (!pa)
{
- pa = GGC_CNEW (struct parm_attr_d);
+ pa = ggc_alloc_cleared_parm_attr_d ();
pa->id = gnat_param;
pa->dim = Dimension;
VEC_safe_push (parm_attr, gc, f_parm_attr_cache, pa);
@@ -1917,9 +1921,9 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
static tree
Case_Statement_to_gnu (Node_Id gnat_node)
{
- tree gnu_result;
- tree gnu_expr;
+ tree gnu_result, gnu_expr, gnu_label;
Node_Id gnat_when;
+ bool may_fallthru = false;
gnu_expr = gnat_to_gnu (Expression (gnat_node));
gnu_expr = convert (get_base_type (TREE_TYPE (gnu_expr)), gnu_expr);
@@ -1942,10 +1946,9 @@ Case_Statement_to_gnu (Node_Id gnat_node)
/* We build a SWITCH_EXPR that contains the code with interspersed
CASE_LABEL_EXPRs for each label. */
-
- push_stack (&gnu_switch_label_stack, NULL_TREE,
- create_artificial_label (input_location));
+ gnu_label = create_artificial_label (input_location);
start_stmt_group ();
+
for (gnat_when = First_Non_Pragma (Alternatives (gnat_node));
Present (gnat_when);
gnat_when = Next_Non_Pragma (gnat_when))
@@ -2023,18 +2026,22 @@ Case_Statement_to_gnu (Node_Id gnat_node)
containing the Case statement. */
if (choices_added_p)
{
- add_stmt (build_stmt_group (Statements (gnat_when), true));
- add_stmt (build1 (GOTO_EXPR, void_type_node,
- TREE_VALUE (gnu_switch_label_stack)));
+ tree group = build_stmt_group (Statements (gnat_when), true);
+ bool group_may_fallthru = block_may_fallthru (group);
+ add_stmt (group);
+ if (group_may_fallthru)
+ {
+ add_stmt (build1 (GOTO_EXPR, void_type_node, gnu_label));
+ may_fallthru = true;
+ }
}
}
- /* Now emit a definition of the label all the cases branched to. */
- add_stmt (build1 (LABEL_EXPR, void_type_node,
- TREE_VALUE (gnu_switch_label_stack)));
+ /* Now emit a definition of the label the cases branch to, if any. */
+ if (may_fallthru)
+ add_stmt (build1 (LABEL_EXPR, void_type_node, gnu_label));
gnu_result = build3 (SWITCH_EXPR, TREE_TYPE (gnu_expr), gnu_expr,
end_stmt_group (), NULL_TREE);
- pop_stack (&gnu_switch_label_stack);
return gnu_result;
}
@@ -2100,7 +2107,7 @@ Loop_Statement_to_gnu (Node_Id gnat_node)
/* Save the end label of this LOOP_STMT in a stack so that a corresponding
N_Exit_Statement can find it. */
- push_stack (&gnu_loop_label_stack, NULL_TREE, gnu_loop_label);
+ VEC_safe_push (tree, gc, gnu_loop_label_stack, gnu_loop_label);
/* Set the condition under which the loop must keep going.
For the case "LOOP .... END LOOP;" the condition is always true. */
@@ -2317,7 +2324,7 @@ Loop_Statement_to_gnu (Node_Id gnat_node)
else
gnu_result = gnu_loop_stmt;
- pop_stack (&gnu_loop_label_stack);
+ VEC_pop (tree, gnu_loop_label_stack);
return gnu_result;
}
@@ -2441,7 +2448,7 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
/* Initialize the information structure for the function. */
allocate_struct_function (gnu_subprog_decl, false);
DECL_STRUCT_FUNCTION (gnu_subprog_decl)->language
- = GGC_CNEW (struct language_function);
+ = ggc_alloc_cleared_language_function ();
set_cfun (NULL);
begin_subprog_body (gnu_subprog_decl);
@@ -2450,9 +2457,10 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
properly copies them out. We do this by making a new block and converting
any inner return into a goto to a label at the end of the block. */
gnu_cico_list = TYPE_CI_CO_LIST (gnu_subprog_type);
- push_stack (&gnu_return_label_stack, NULL_TREE,
- gnu_cico_list ? create_artificial_label (input_location)
- : NULL_TREE);
+ VEC_safe_push (tree, gc, gnu_return_label_stack,
+ gnu_cico_list
+ ? create_artificial_label (input_location)
+ : NULL_TREE);
/* Get a tree corresponding to the code for the subprogram. */
start_stmt_group ();
@@ -2470,9 +2478,8 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
{
/* Skip any entries that have been already filled in; they must
correspond to In Out parameters. */
- for (; gnu_cico_list && TREE_VALUE (gnu_cico_list);
- gnu_cico_list = TREE_CHAIN (gnu_cico_list))
- ;
+ while (gnu_cico_list && TREE_VALUE (gnu_cico_list))
+ gnu_cico_list = TREE_CHAIN (gnu_cico_list);
/* Do any needed references for padded types. */
TREE_VALUE (gnu_cico_list)
@@ -2540,7 +2547,7 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
We need to make a block that contains the definition of that label and
the copying of the return value. It first contains the function, then
the label and copy statement. */
- if (TREE_VALUE (gnu_return_label_stack))
+ if (VEC_last (tree, gnu_return_label_stack))
{
tree gnu_retval;
@@ -2548,14 +2555,14 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
gnat_pushlevel ();
add_stmt (gnu_result);
add_stmt (build1 (LABEL_EXPR, void_type_node,
- TREE_VALUE (gnu_return_label_stack)));
+ VEC_last (tree, gnu_return_label_stack)));
gnu_cico_list = TYPE_CI_CO_LIST (gnu_subprog_type);
if (list_length (gnu_cico_list) == 1)
gnu_retval = TREE_VALUE (gnu_cico_list);
else
- gnu_retval = gnat_build_constructor (TREE_TYPE (gnu_subprog_type),
- gnu_cico_list);
+ gnu_retval = build_constructor_from_list (TREE_TYPE (gnu_subprog_type),
+ gnu_cico_list);
add_stmt_with_node (build_return_expr (gnu_result_decl, gnu_retval),
End_Label (Handled_Statement_Sequence (gnat_node)));
@@ -2563,7 +2570,7 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
gnu_result = end_stmt_group ();
}
- pop_stack (&gnu_return_label_stack);
+ VEC_pop (tree, gnu_return_label_stack);
/* Set the end location. */
Sloc_to_locus
@@ -2666,7 +2673,7 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
so we can give them the scope of the elaboration routine at top level. */
else if (!current_function_decl)
{
- current_function_decl = TREE_VALUE (gnu_elab_proc_stack);
+ current_function_decl = VEC_last (tree, gnu_elab_proc_stack);
went_into_elab_proc = true;
}
@@ -3260,12 +3267,13 @@ Handled_Sequence_Of_Statements_to_gnu (Node_Id gnat_node)
start_stmt_group ();
gnat_pushlevel ();
- push_stack (&gnu_except_ptr_stack, NULL_TREE,
- create_var_decl (get_identifier ("EXCEPT_PTR"),
- NULL_TREE,
- build_pointer_type (except_type_node),
- build_call_0_expr (get_excptr_decl), false,
- false, false, false, NULL, gnat_node));
+ VEC_safe_push (tree, gc, gnu_except_ptr_stack,
+ create_var_decl (get_identifier ("EXCEPT_PTR"),
+ NULL_TREE,
+ build_pointer_type (except_type_node),
+ build_call_0_expr (get_excptr_decl),
+ false,
+ false, false, false, NULL, gnat_node));
/* Generate code for each handler. The N_Exception_Handler case does the
real work and returns a COND_EXPR for each handler, which we chain
@@ -3289,7 +3297,7 @@ Handled_Sequence_Of_Statements_to_gnu (Node_Id gnat_node)
/* If none of the exception handlers did anything, re-raise but do not
defer abortion. */
gnu_expr = build_call_1_expr (raise_nodefer_decl,
- TREE_VALUE (gnu_except_ptr_stack));
+ VEC_last (tree, gnu_except_ptr_stack));
set_expr_location_from_node
(gnu_expr,
Present (End_Label (gnat_node)) ? End_Label (gnat_node) : gnat_node);
@@ -3301,7 +3309,7 @@ Handled_Sequence_Of_Statements_to_gnu (Node_Id gnat_node)
/* End the binding level dedicated to the exception handlers and get the
whole statement group. */
- pop_stack (&gnu_except_ptr_stack);
+ VEC_pop (tree, gnu_except_ptr_stack);
gnat_poplevel ();
gnu_handler = end_stmt_group ();
@@ -3385,7 +3393,7 @@ Exception_Handler_to_gnu_sjlj (Node_Id gnat_node)
build_component_ref
(build_unary_op
(INDIRECT_REF, NULL_TREE,
- TREE_VALUE (gnu_except_ptr_stack)),
+ VEC_last (tree, gnu_except_ptr_stack)),
get_identifier ("not_handled_by_others"), NULL_TREE,
false)),
integer_zero_node);
@@ -3406,8 +3414,9 @@ Exception_Handler_to_gnu_sjlj (Node_Id gnat_node)
this_choice
= build_binary_op
- (EQ_EXPR, boolean_type_node, TREE_VALUE (gnu_except_ptr_stack),
- convert (TREE_TYPE (TREE_VALUE (gnu_except_ptr_stack)),
+ (EQ_EXPR, boolean_type_node,
+ VEC_last (tree, gnu_except_ptr_stack),
+ convert (TREE_TYPE (VEC_last (tree, gnu_except_ptr_stack)),
build_unary_op (ADDR_EXPR, NULL_TREE, gnu_expr)));
/* If this is the distinguished exception "Non_Ada_Error" (and we are
@@ -3418,7 +3427,7 @@ Exception_Handler_to_gnu_sjlj (Node_Id gnat_node)
tree gnu_comp
= build_component_ref
(build_unary_op (INDIRECT_REF, NULL_TREE,
- TREE_VALUE (gnu_except_ptr_stack)),
+ VEC_last (tree, gnu_except_ptr_stack)),
get_identifier ("lang"), NULL_TREE, false);
this_choice
@@ -3555,7 +3564,7 @@ Compilation_Unit_to_gnu (Node_Id gnat_node)
NULL_TREE, void_ftype, NULL_TREE, false, true, false, NULL, gnat_unit);
struct elab_info *info;
- push_stack (&gnu_elab_proc_stack, NULL_TREE, gnu_elab_proc_decl);
+ VEC_safe_push (tree, gc, gnu_elab_proc_stack, gnu_elab_proc_decl);
DECL_ELABORATION_PROC_P (gnu_elab_proc_decl) = 1;
/* Initialize the information structure for the function. */
@@ -3626,7 +3635,7 @@ Compilation_Unit_to_gnu (Node_Id gnat_node)
/* Save away what we've made so far and record this potential elaboration
procedure. */
- info = (struct elab_info *) ggc_alloc (sizeof (struct elab_info));
+ info = ggc_alloc_elab_info ();
set_current_block_context (gnu_elab_proc_decl);
gnat_poplevel ();
DECL_SAVED_TREE (gnu_elab_proc_decl) = end_stmt_group ();
@@ -3642,7 +3651,7 @@ Compilation_Unit_to_gnu (Node_Id gnat_node)
/* Generate elaboration code for this unit, if necessary, and say whether
we did or not. */
- pop_stack (&gnu_elab_proc_stack);
+ VEC_pop (tree, gnu_elab_proc_stack);
/* Invalidate the global renaming pointers. This is necessary because
stabilization of the renamed entities may create SAVE_EXPRs which
@@ -3744,7 +3753,7 @@ gnat_to_gnu (Node_Id gnat_node)
the elaboration procedure, so mark us as being in that procedure. */
if (!current_function_decl)
{
- current_function_decl = TREE_VALUE (gnu_elab_proc_stack);
+ current_function_decl = VEC_last (tree, gnu_elab_proc_stack);
went_into_elab_proc = true;
}
@@ -3755,7 +3764,7 @@ gnat_to_gnu (Node_Id gnat_node)
every nested real statement instead. This also avoids triggering
spurious errors on dummy (empty) sequences created by the front-end
for package bodies in some cases. */
- if (current_function_decl == TREE_VALUE (gnu_elab_proc_stack)
+ if (current_function_decl == VEC_last (tree, gnu_elab_proc_stack)
&& kind != N_Handled_Sequence_Of_Statements)
Check_Elaboration_Code_Allowed (gnat_node);
}
@@ -3918,24 +3927,21 @@ gnat_to_gnu (Node_Id gnat_node)
String_Id gnat_string = Strval (gnat_node);
int length = String_Length (gnat_string);
int i;
- tree gnu_list = NULL_TREE;
tree gnu_idx = TYPE_MIN_VALUE (TYPE_DOMAIN (gnu_result_type));
+ VEC(constructor_elt,gc) *gnu_vec
+ = VEC_alloc (constructor_elt, gc, length);
for (i = 0; i < length; i++)
{
- gnu_list
- = tree_cons (gnu_idx,
- build_int_cst (TREE_TYPE (gnu_result_type),
- Get_String_Char (gnat_string,
- i + 1)),
- gnu_list);
+ tree t = build_int_cst (TREE_TYPE (gnu_result_type),
+ Get_String_Char (gnat_string, i + 1));
+ CONSTRUCTOR_APPEND_ELT (gnu_vec, gnu_idx, t);
gnu_idx = int_const_binop (PLUS_EXPR, gnu_idx, integer_one_node,
0);
}
- gnu_result
- = gnat_build_constructor (gnu_result_type, nreverse (gnu_list));
+ gnu_result = gnat_build_constructor (gnu_result_type, gnu_vec);
}
break;
@@ -4323,7 +4329,7 @@ gnat_to_gnu (Node_Id gnat_node)
gnu_aggr_type = TYPE_REPRESENTATIVE_ARRAY (gnu_result_type);
if (Null_Record_Present (gnat_node))
- gnu_result = gnat_build_constructor (gnu_aggr_type, NULL_TREE);
+ gnu_result = gnat_build_constructor (gnu_aggr_type, NULL);
else if (TREE_CODE (gnu_aggr_type) == RECORD_TYPE
|| TREE_CODE (gnu_aggr_type) == UNION_TYPE)
@@ -4879,7 +4885,7 @@ gnat_to_gnu (Node_Id gnat_node)
? gnat_to_gnu (Condition (gnat_node)) : NULL_TREE),
(Present (Name (gnat_node))
? get_gnu_tree (Entity (Name (gnat_node)))
- : TREE_VALUE (gnu_loop_label_stack)));
+ : VEC_last (tree, gnu_loop_label_stack)));
break;
case N_Return_Statement:
@@ -4888,13 +4894,13 @@ gnat_to_gnu (Node_Id gnat_node)
/* If we have a return label defined, convert this into a branch to
that label. The return proper will be handled elsewhere. */
- if (TREE_VALUE (gnu_return_label_stack))
+ if (VEC_last (tree, gnu_return_label_stack))
{
gnu_result = build1 (GOTO_EXPR, void_type_node,
- TREE_VALUE (gnu_return_label_stack));
+ VEC_last (tree, gnu_return_label_stack));
/* When not optimizing, make sure the return is preserved. */
if (!optimize && Comes_From_Source (gnat_node))
- DECL_ARTIFICIAL (TREE_VALUE (gnu_return_label_stack)) = 0;
+ DECL_ARTIFICIAL (VEC_last (tree, gnu_return_label_stack)) = 0;
break;
}
@@ -5154,18 +5160,15 @@ gnat_to_gnu (Node_Id gnat_node)
break;
case N_Pop_Constraint_Error_Label:
- gnu_constraint_error_label_stack
- = TREE_CHAIN (gnu_constraint_error_label_stack);
+ VEC_pop (tree, gnu_constraint_error_label_stack);
break;
case N_Pop_Storage_Error_Label:
- gnu_storage_error_label_stack
- = TREE_CHAIN (gnu_storage_error_label_stack);
+ VEC_pop (tree, gnu_storage_error_label_stack);
break;
case N_Pop_Program_Error_Label:
- gnu_program_error_label_stack
- = TREE_CHAIN (gnu_program_error_label_stack);
+ VEC_pop (tree, gnu_program_error_label_stack);
break;
/******************************/
@@ -5327,6 +5330,19 @@ gnat_to_gnu (Node_Id gnat_node)
/* Added Nodes */
/****************/
+ case N_Expression_With_Actions:
+ gnu_result_type = get_unpadded_type (Etype (gnat_node));
+ /* This construct doesn't define a scope so we don't wrap the statement
+ list in a BIND_EXPR; however, we wrap it in a SAVE_EXPR to protect it
+ from unsharing. */
+ gnu_result = build_stmt_group (Actions (gnat_node), false);
+ gnu_result = build1 (SAVE_EXPR, void_type_node, gnu_result);
+ TREE_SIDE_EFFECTS (gnu_result) = 1;
+ gnu_expr = gnat_to_gnu (Expression (gnat_node));
+ gnu_result
+ = build2 (COMPOUND_EXPR, TREE_TYPE (gnu_expr), gnu_result, gnu_expr);
+ break;
+
case N_Freeze_Entity:
start_stmt_group ();
process_freeze_entity (gnat_node);
@@ -5546,17 +5562,11 @@ gnat_to_gnu (Node_Id gnat_node)
convert (gnu_result_type,
boolean_false_node));
- /* Set the location information on the result if it is a real expression.
- References can be reused for multiple GNAT nodes and they would get
- the location information of their last use. Note that we may have
+ /* Set the location information on the result. Note that we may have
no result if we tried to build a CALL_EXPR node to a procedure with
no side-effects and optimization is enabled. */
- if (gnu_result
- && EXPR_P (gnu_result)
- && TREE_CODE (gnu_result) != NOP_EXPR
- && !REFERENCE_CLASS_P (gnu_result)
- && !EXPR_HAS_LOCATION (gnu_result))
- set_expr_location_from_node (gnu_result, gnat_node);
+ if (gnu_result && EXPR_P (gnu_result))
+ set_gnu_expr_location_from_node (gnu_result, gnat_node);
/* If we're supposed to return something of void_type, it means we have
something we're elaborating for effect, so just return. */
@@ -5682,13 +5692,13 @@ gnat_to_gnu (Node_Id gnat_node)
label to push onto the stack. */
static void
-push_exception_label_stack (tree *gnu_stack, Entity_Id gnat_label)
+push_exception_label_stack (VEC(tree,gc) **gnu_stack, Entity_Id gnat_label)
{
tree gnu_label = (Present (gnat_label)
? gnat_to_gnu_entity (gnat_label, NULL_TREE, 0)
: NULL_TREE);
- *gnu_stack = tree_cons (NULL_TREE, gnu_label, *gnu_stack);
+ VEC_safe_push (tree, gc, *gnu_stack, gnu_label);
}
/* Record the current code position in GNAT_NODE. */
@@ -5722,7 +5732,7 @@ start_stmt_group (void)
if (group)
stmt_group_free_list = group->previous;
else
- group = (struct stmt_group *) ggc_alloc (sizeof (struct stmt_group));
+ group = ggc_alloc_stmt_group ();
group->previous = current_stmt_group;
group->stmt_list = group->block = group->cleanups = NULL_TREE;
@@ -5938,37 +5948,6 @@ build_stmt_group (List_Id gnat_list, bool binding_p)
return end_stmt_group ();
}
-/* Push and pop routines for stacks. We keep a free list around so we
- don't waste tree nodes. */
-
-static void
-push_stack (tree *gnu_stack_ptr, tree gnu_purpose, tree gnu_value)
-{
- tree gnu_node = gnu_stack_free_list;
-
- if (gnu_node)
- {
- gnu_stack_free_list = TREE_CHAIN (gnu_node);
- TREE_CHAIN (gnu_node) = *gnu_stack_ptr;
- TREE_PURPOSE (gnu_node) = gnu_purpose;
- TREE_VALUE (gnu_node) = gnu_value;
- }
- else
- gnu_node = tree_cons (gnu_purpose, gnu_value, *gnu_stack_ptr);
-
- *gnu_stack_ptr = gnu_node;
-}
-
-static void
-pop_stack (tree *gnu_stack_ptr)
-{
- tree gnu_node = *gnu_stack_ptr;
-
- *gnu_stack_ptr = TREE_CHAIN (gnu_node);
- TREE_CHAIN (gnu_node) = gnu_stack_free_list;
- gnu_stack_free_list = gnu_node;
-}
-
/* Generate GIMPLE in place for the expression at *EXPR_P. */
int
@@ -7340,9 +7319,9 @@ static tree
pos_to_constructor (Node_Id gnat_expr, tree gnu_array_type,
Entity_Id gnat_component_type)
{
- tree gnu_expr_list = NULL_TREE;
tree gnu_index = TYPE_MIN_VALUE (TYPE_DOMAIN (gnu_array_type));
tree gnu_expr;
+ VEC(constructor_elt,gc) *gnu_expr_vec = NULL;
for ( ; Present (gnat_expr); gnat_expr = Next (gnat_expr))
{
@@ -7365,14 +7344,13 @@ pos_to_constructor (Node_Id gnat_expr, tree gnu_array_type,
gnu_expr = emit_range_check (gnu_expr, gnat_component_type, Empty);
}
- gnu_expr_list
- = tree_cons (gnu_index, convert (TREE_TYPE (gnu_array_type), gnu_expr),
- gnu_expr_list);
+ CONSTRUCTOR_APPEND_ELT (gnu_expr_vec, gnu_index,
+ convert (TREE_TYPE (gnu_array_type), gnu_expr));
gnu_index = int_const_binop (PLUS_EXPR, gnu_index, integer_one_node, 0);
}
- return gnat_build_constructor (gnu_array_type, nreverse (gnu_expr_list));
+ return gnat_build_constructor (gnu_array_type, gnu_expr_vec);
}
/* Subroutine of assoc_to_constructor: VALUES is a list of field associations,
@@ -7383,8 +7361,8 @@ pos_to_constructor (Node_Id gnat_expr, tree gnu_array_type,
static tree
extract_values (tree values, tree record_type)
{
- tree result = NULL_TREE;
tree field, tem;
+ VEC(constructor_elt,gc) *v = NULL;
for (field = TYPE_FIELDS (record_type); field; field = TREE_CHAIN (field))
{
@@ -7418,10 +7396,10 @@ extract_values (tree values, tree record_type)
if (!value)
continue;
- result = tree_cons (field, value, result);
+ CONSTRUCTOR_APPEND_ELT (v, field, value);
}
- return gnat_build_constructor (record_type, nreverse (result));
+ return gnat_build_constructor (record_type, v);
}
/* EXP is to be treated as an array or record. Handle the cases when it is
@@ -7491,6 +7469,37 @@ set_expr_location_from_node (tree node, Node_Id gnat_node)
SET_EXPR_LOCATION (node, locus);
}
+
+/* More elaborate version of set_expr_location_from_node to be used in more
+ general contexts, for example the result of the translation of a generic
+ GNAT node. */
+
+static void
+set_gnu_expr_location_from_node (tree node, Node_Id gnat_node)
+{
+ /* Set the location information on the node if it is a real expression.
+ References can be reused for multiple GNAT nodes and they would get
+ the location information of their last use. Also make sure not to
+ overwrite an existing location as it is probably more precise. */
+
+ switch (TREE_CODE (node))
+ {
+ CASE_CONVERT:
+ case NON_LVALUE_EXPR:
+ break;
+
+ case COMPOUND_EXPR:
+ if (EXPR_P (TREE_OPERAND (node, 1)))
+ set_gnu_expr_location_from_node (TREE_OPERAND (node, 1), gnat_node);
+
+ /* ... fall through ... */
+
+ default:
+ if (!REFERENCE_CLASS_P (node) && !EXPR_HAS_LOCATION (node))
+ set_expr_location_from_node (node, gnat_node);
+ break;
+ }
+}
/* Return a colon-separated list of encodings contained in encoded Ada
name. */
@@ -7498,7 +7507,7 @@ set_expr_location_from_node (tree node, Node_Id gnat_node)
static const char *
extract_encoding (const char *name)
{
- char *encoding = GGC_NEWVEC (char, strlen (name));
+ char *encoding = (char *) ggc_alloc_atomic (strlen (name));
get_encoding (name, encoding);
return encoding;
}
@@ -7508,7 +7517,7 @@ extract_encoding (const char *name)
static const char *
decode_name (const char *name)
{
- char *decoded = GGC_NEWVEC (char, strlen (name) * 2 + 60);
+ char *decoded = (char *) ggc_alloc_atomic (strlen (name) * 2 + 60);
__gnat_decode (name, decoded, 0);
return decoded;
}
@@ -7641,11 +7650,11 @@ tree
get_exception_label (char kind)
{
if (kind == N_Raise_Constraint_Error)
- return TREE_VALUE (gnu_constraint_error_label_stack);
+ return VEC_last (tree, gnu_constraint_error_label_stack);
else if (kind == N_Raise_Storage_Error)
- return TREE_VALUE (gnu_storage_error_label_stack);
+ return VEC_last (tree, gnu_storage_error_label_stack);
else if (kind == N_Raise_Program_Error)
- return TREE_VALUE (gnu_program_error_label_stack);
+ return VEC_last (tree, gnu_program_error_label_stack);
else
return NULL_TREE;
}