diff options
author | hjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-07-01 22:22:57 +0000 |
---|---|---|
committer | hjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-07-01 22:22:57 +0000 |
commit | 9e169c4bf36a38689550c059570c57efbf00a6fb (patch) | |
tree | 95e6800f7ac2a49ff7f799d96f04172320e70ac0 /gcc/ada/gcc-interface/trans.c | |
parent | 6170dfb6edfb7b19f8ae5209b8f948fe0076a4ad (diff) | |
download | gcc-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.c | 331 |
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; } |