From: Richard Henderson Date: Wed, 11 Aug 2004 04:16:07 +0000 (-0700) Subject: builtins.def (BUILT_IN_STACK_ALLOC): Remove. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1a186ec5586436555a30227776d75c2516fd5911;p=gcc.git builtins.def (BUILT_IN_STACK_ALLOC): Remove. * builtins.def (BUILT_IN_STACK_ALLOC): Remove. * builtins.c (expand_builtin) : Remove. * dwarf2out.c (loc_descriptor): Handle PARALLEL here ... (add_location_or_const_value_attribute): ... not here. Use loc_descriptor_from_tree if possible. (loc_descriptor_from_tree_1): Rename from loc_descriptor_from_tree. Simplify address handling. Handle DECL_VALUE_EXPR. Handle register values specially. (loc_descriptor_from_tree): New. Update callers. * expr.c (expand_var): Ignore DECL_VALUE_EXPR variables. * gimplify.c (gimplify_decl_expr): Lower variable sized types to pointer plus dereference. Set DECL_VALUE_EXPR. Set save_stack. (gimplify_call_expr): Do not recognize BUILT_IN_STACK_ALLOC and BUILT_IN_STACK_RESTORE. (gimplify_expr): Lower DECL_VALUE_EXPR decls. * stmt.c (expand_stack_alloc): Remove. * tree-mudflap.c (mx_register_decls): Don't look for BUILT_IN_STACK_ALLOC. * tree-nested.c (convert_local_reference): Likewise. * tree.h (DECL_VALUE_EXPR): New. ada/ * utils.c (gnat_install_builtins): Remove __builtin_stack_alloc, add __builtin_alloca. fortran/ * f95-lang.c (gfc_init_builtin_functions): Remove __builtin_stack_alloc, add __builtin_alloca. * trans-array.c (gfc_trans_auto_array_allocation): Use DECL_EXPR. * trans-decl.c (gfc_trans_auto_character_variable): Likewise. From-SVN: r85794 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a51da9b7310..ffa4aeeaa88 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,26 @@ +2004-08-10 Richard Henderson + + * builtins.def (BUILT_IN_STACK_ALLOC): Remove. + * builtins.c (expand_builtin) : Remove. + * dwarf2out.c (loc_descriptor): Handle PARALLEL here ... + (add_location_or_const_value_attribute): ... not here. Use + loc_descriptor_from_tree if possible. + (loc_descriptor_from_tree_1): Rename from loc_descriptor_from_tree. + Simplify address handling. Handle DECL_VALUE_EXPR. Handle register + values specially. + (loc_descriptor_from_tree): New. Update callers. + * expr.c (expand_var): Ignore DECL_VALUE_EXPR variables. + * gimplify.c (gimplify_decl_expr): Lower variable sized types to + pointer plus dereference. Set DECL_VALUE_EXPR. Set save_stack. + (gimplify_call_expr): Do not recognize BUILT_IN_STACK_ALLOC + and BUILT_IN_STACK_RESTORE. + (gimplify_expr): Lower DECL_VALUE_EXPR decls. + * stmt.c (expand_stack_alloc): Remove. + * tree-mudflap.c (mx_register_decls): Don't look for + BUILT_IN_STACK_ALLOC. + * tree-nested.c (convert_local_reference): Likewise. + * tree.h (DECL_VALUE_EXPR): New. + 2004-08-10 Richard Henderson * stor-layout.c (round_up): Check for 0/1 before dividing. diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 071390196ef..9cb2dfdb4a9 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2004-08-10 Richard Henderson + + * utils.c (gnat_install_builtins): Remove __builtin_stack_alloc, + add __builtin_alloca. + 2004-08-10 Richard Henderson * config-lang.in (boot_language): Yes. diff --git a/gcc/ada/utils.c b/gcc/ada/utils.c index 46c5639480b..4f2362981c5 100644 --- a/gcc/ada/utils.c +++ b/gcc/ada/utils.c @@ -481,6 +481,9 @@ gnat_install_builtins () gnat_define_builtin ("__builtin_clzll", ftype, BUILT_IN_CLZLL, "clzll", true); + /* The init_trampoline and adjust_trampoline builtins aren't used directly. + They are inserted during lowering of nested functions. */ + tmp = tree_cons (NULL_TREE, ptr_void_type_node, void_list_node); tmp = tree_cons (NULL_TREE, ptr_void_type_node, tmp); tmp = tree_cons (NULL_TREE, ptr_void_type_node, tmp); @@ -493,21 +496,24 @@ gnat_install_builtins () gnat_define_builtin ("__builtin_adjust_trampoline", ftype, BUILT_IN_ADJUST_TRAMPOLINE, "adjust_trampoline", true); - tmp = tree_cons (NULL_TREE, ptr_void_type_node, void_list_node); - tmp = tree_cons (NULL_TREE, size_type_node, void_list_node); - ftype = build_function_type (ptr_void_type_node, tmp); - gnat_define_builtin ("__builtin_stack_alloc", ftype, BUILT_IN_STACK_ALLOC, - "stack_alloc", false); + /* The stack_save, stack_restore, and alloca builtins aren't used directly. + They are inserted during gimplification to implement variable sized stack + allocation. */ - /* The stack_save and stack_restore builtins aren't used directly. They - are inserted during gimplification to implement stack_alloc calls. */ ftype = build_function_type (ptr_void_type_node, void_list_node); gnat_define_builtin ("__builtin_stack_save", ftype, BUILT_IN_STACK_SAVE, "stack_save", false); + tmp = tree_cons (NULL_TREE, ptr_void_type_node, void_list_node); ftype = build_function_type (void_type_node, tmp); gnat_define_builtin ("__builtin_stack_restore", ftype, BUILT_IN_STACK_RESTORE, "stack_restore", false); + + tmp = tree_cons (NULL_TREE, size_type_node, void_list_node); + ftype = build_function_type (ptr_void_type_node, tmp); + gnat_define_builtin ("__builtin_alloca", ftype, BUILT_IN_ALLOCA, + "alloca", false); + } /* Create the predefined scalar types such as `integer_type_node' needed diff --git a/gcc/builtins.c b/gcc/builtins.c index bb32f1202e9..fb852ff0b55 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -5756,11 +5756,6 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, return target; break; - case BUILT_IN_STACK_ALLOC: - expand_stack_alloc (TREE_VALUE (arglist), - TREE_VALUE (TREE_CHAIN (arglist))); - return const0_rtx; - case BUILT_IN_STACK_SAVE: return expand_stack_save (); diff --git a/gcc/builtins.def b/gcc/builtins.def index d660f8d590e..1cfbf712999 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -607,7 +607,6 @@ DEF_GCC_BUILTIN (BUILT_IN_RETURN, "return", BT_FN_VOID_PTR, ATTR_NORETURN DEF_GCC_BUILTIN (BUILT_IN_RETURN_ADDRESS, "return_address", BT_FN_PTR_UINT, ATTR_NULL) DEF_GCC_BUILTIN (BUILT_IN_SAVEREGS, "saveregs", BT_FN_PTR_VAR, ATTR_NULL) DEF_GCC_BUILTIN (BUILT_IN_SETJMP, "setjmp", BT_FN_INT_PTR, ATTR_NULL) -DEF_GCC_BUILTIN (BUILT_IN_STACK_ALLOC, "stack_alloc", BT_FN_VOID_PTR_SIZE, ATTR_NULL) DEF_GCC_BUILTIN (BUILT_IN_STACK_SAVE, "stack_save", BT_FN_PTR, ATTR_NULL) DEF_GCC_BUILTIN (BUILT_IN_STACK_RESTORE, "stack_restore", BT_FN_VOID_PTR, ATTR_NULL) DEF_GCC_BUILTIN (BUILT_IN_STDARG_START, "stdarg_start", BT_FN_VOID_VALIST_REF_VAR, ATTR_NULL) diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 46b3b512660..242a653b278 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -3907,7 +3907,8 @@ static int is_based_loc (rtx); static dw_loc_descr_ref mem_loc_descriptor (rtx, enum machine_mode mode, bool); static dw_loc_descr_ref concat_loc_descriptor (rtx, rtx); static dw_loc_descr_ref loc_descriptor (rtx, bool); -static dw_loc_descr_ref loc_descriptor_from_tree (tree, int); +static dw_loc_descr_ref loc_descriptor_from_tree_1 (tree, int); +static dw_loc_descr_ref loc_descriptor_from_tree (tree); static HOST_WIDE_INT ceiling (HOST_WIDE_INT, unsigned int); static tree field_type (tree); static unsigned int simple_type_align_in_bits (tree); @@ -8805,34 +8806,38 @@ loc_descriptor (rtx rtl, bool can_use_fbreg) if (GET_CODE (XEXP (rtl, 1)) != PARALLEL) { loc_result = loc_descriptor (XEXP (XEXP (rtl, 1), 0), can_use_fbreg); + break; } - /* Multiple parts. */ - else - { - rtvec par_elems = XVEC (XEXP (rtl, 1), 0); - int num_elem = GET_NUM_ELEM (par_elems); - enum machine_mode mode; - int i; - /* Create the first one, so we have something to add to. */ - loc_result = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0), - can_use_fbreg); - mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0)); - add_loc_descr (&loc_result, - new_loc_descr (DW_OP_piece, GET_MODE_SIZE (mode), 0)); - for (i = 1; i < num_elem; i++) - { - dw_loc_descr_ref temp; + rtl = XEXP (rtl, 1); + /* FALLTHRU */ - temp = loc_descriptor (XEXP (RTVEC_ELT (par_elems, i), 0), + case PARALLEL: + { + rtvec par_elems = XVEC (rtl, 0); + int num_elem = GET_NUM_ELEM (par_elems); + enum machine_mode mode; + int i; + + /* Create the first one, so we have something to add to. */ + loc_result = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0), can_use_fbreg); - add_loc_descr (&loc_result, temp); - mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0)); - add_loc_descr (&loc_result, - new_loc_descr (DW_OP_piece, - GET_MODE_SIZE (mode), 0)); - } - } + mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0)); + add_loc_descr (&loc_result, + new_loc_descr (DW_OP_piece, GET_MODE_SIZE (mode), 0)); + for (i = 1; i < num_elem; i++) + { + dw_loc_descr_ref temp; + + temp = loc_descriptor (XEXP (RTVEC_ELT (par_elems, i), 0), + can_use_fbreg); + add_loc_descr (&loc_result, temp); + mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0)); + add_loc_descr (&loc_result, + new_loc_descr (DW_OP_piece, + GET_MODE_SIZE (mode), 0)); + } + } break; default: @@ -8843,15 +8848,16 @@ loc_descriptor (rtx rtl, bool can_use_fbreg) } /* Similar, but generate the descriptor from trees instead of rtl. This comes - up particularly with variable length arrays. If ADDRESSP is nonzero, we are - looking for an address. Otherwise, we return a value. If we can't make a - descriptor, return 0. */ + up particularly with variable length arrays. WANT_ADDRESS is 2 if this is + a top-level invocation of loc_descriptor_from_tree; is 1 if this is not a + top-level invocation, and we require the address of LOC; is 0 if we require + the value of LOC. */ static dw_loc_descr_ref -loc_descriptor_from_tree (tree loc, int addressp) +loc_descriptor_from_tree_1 (tree loc, int want_address) { dw_loc_descr_ref ret, ret1; - int indirect_p = 0; + int have_address = 0; int unsignedp = TYPE_UNSIGNED (TREE_TYPE (loc)); enum dwarf_location_atom op; @@ -8882,19 +8888,12 @@ loc_descriptor_from_tree (tree loc, int addressp) return 0; case ADDR_EXPR: - /* We can support this only if we can look through conversions and - find an INDIRECT_EXPR. */ - for (loc = TREE_OPERAND (loc, 0); - TREE_CODE (loc) == CONVERT_EXPR || TREE_CODE (loc) == NOP_EXPR - || TREE_CODE (loc) == NON_LVALUE_EXPR - || TREE_CODE (loc) == VIEW_CONVERT_EXPR - || TREE_CODE (loc) == SAVE_EXPR; - loc = TREE_OPERAND (loc, 0)) - ; + /* If we already want an address, there's nothing we can do. */ + if (want_address) + return 0; - return (TREE_CODE (loc) == INDIRECT_REF - ? loc_descriptor_from_tree (TREE_OPERAND (loc, 0), addressp) - : 0); + /* Otherwise, process the argument and look for the address. */ + return loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 1); case VAR_DECL: if (DECL_THREAD_LOCAL (loc)) @@ -8928,47 +8927,63 @@ loc_descriptor_from_tree (tree loc, int addressp) ret1 = new_loc_descr (DW_OP_GNU_push_tls_address, 0, 0); add_loc_descr (&ret, ret1); - indirect_p = 1; + have_address = 1; break; } - /* Fall through. */ + /* FALLTHRU */ case PARM_DECL: + if (DECL_VALUE_EXPR (loc)) + return loc_descriptor_from_tree_1 (DECL_VALUE_EXPR (loc), want_address); + /* FALLTHRU */ + case RESULT_DECL: { rtx rtl = rtl_for_decl_location (loc); if (rtl == NULL_RTX) return 0; + else if (GET_CODE (rtl) == CONST_INT) + { + HOST_WIDE_INT val = INTVAL (rtl); + if (TYPE_UNSIGNED (TREE_TYPE (loc))) + val &= GET_MODE_MASK (DECL_MODE (loc)); + ret = int_loc_descriptor (val); + } + else if (GET_CODE (rtl) == CONST_STRING) + return 0; else if (CONSTANT_P (rtl)) { ret = new_loc_descr (DW_OP_addr, 0, 0); ret->dw_loc_oprnd1.val_class = dw_val_class_addr; ret->dw_loc_oprnd1.v.val_addr = rtl; - indirect_p = 1; } else { - enum machine_mode mode = GET_MODE (rtl); + enum machine_mode mode; + + /* Certain constructs can only be represented at top-level. */ + if (want_address == 2) + return loc_descriptor (rtl, true); + mode = GET_MODE (rtl); if (MEM_P (rtl)) { - indirect_p = 1; rtl = XEXP (rtl, 0); + have_address = 1; } - ret = mem_loc_descriptor (rtl, mode, true); } } break; case INDIRECT_REF: - ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0); - indirect_p = 1; + ret = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 0); + have_address = 1; break; case COMPOUND_EXPR: - return loc_descriptor_from_tree (TREE_OPERAND (loc, 1), addressp); + return loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 1), want_address); case NOP_EXPR: case CONVERT_EXPR: @@ -8976,7 +8991,7 @@ loc_descriptor_from_tree (tree loc, int addressp) case VIEW_CONVERT_EXPR: case SAVE_EXPR: case MODIFY_EXPR: - return loc_descriptor_from_tree (TREE_OPERAND (loc, 0), addressp); + return loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), want_address); case COMPONENT_REF: case BIT_FIELD_REF: @@ -8994,7 +9009,7 @@ loc_descriptor_from_tree (tree loc, int addressp) if (obj == loc) return 0; - ret = loc_descriptor_from_tree (obj, 1); + ret = loc_descriptor_from_tree_1 (obj, 1); if (ret == 0 || bitpos % BITS_PER_UNIT != 0 || bitsize % BITS_PER_UNIT != 0) return 0; @@ -9002,13 +9017,10 @@ loc_descriptor_from_tree (tree loc, int addressp) if (offset != NULL_TREE) { /* Variable offset. */ - add_loc_descr (&ret, loc_descriptor_from_tree (offset, 0)); + add_loc_descr (&ret, loc_descriptor_from_tree_1 (offset, 0)); add_loc_descr (&ret, new_loc_descr (DW_OP_plus, 0, 0)); } - if (!addressp) - indirect_p = 1; - bytepos = bitpos / BITS_PER_UNIT; if (bytepos > 0) add_loc_descr (&ret, new_loc_descr (DW_OP_plus_uconst, bytepos, 0)); @@ -9017,6 +9029,8 @@ loc_descriptor_from_tree (tree loc, int addressp) add_loc_descr (&ret, int_loc_descriptor (bytepos)); add_loc_descr (&ret, new_loc_descr (DW_OP_plus, 0, 0)); } + + have_address = 1; break; } @@ -9033,15 +9047,12 @@ loc_descriptor_from_tree (tree loc, int addressp) rtx rtl = lookup_constant_def (loc); enum machine_mode mode; - if (!MEM_P (rtl)) + if (!rtl || !MEM_P (rtl)) return 0; mode = GET_MODE (rtl); rtl = XEXP (rtl, 0); - - rtl = targetm.delegitimize_address (rtl); - - indirect_p = 1; ret = mem_loc_descriptor (rtl, mode, true); + have_address = 1; break; } @@ -9096,7 +9107,7 @@ loc_descriptor_from_tree (tree loc, int addressp) if (TREE_CODE (TREE_OPERAND (loc, 1)) == INTEGER_CST && host_integerp (TREE_OPERAND (loc, 1), 0)) { - ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0); + ret = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 0); if (ret == 0) return 0; @@ -9148,8 +9159,8 @@ loc_descriptor_from_tree (tree loc, int addressp) goto do_binop; do_binop: - ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0); - ret1 = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0); + ret = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 0); + ret1 = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 1), 0); if (ret == 0 || ret1 == 0) return 0; @@ -9171,7 +9182,7 @@ loc_descriptor_from_tree (tree loc, int addressp) goto do_unop; do_unop: - ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0); + ret = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 0); if (ret == 0) return 0; @@ -9187,7 +9198,7 @@ loc_descriptor_from_tree (tree loc, int addressp) loc = build3 (COND_EXPR, TREE_TYPE (loc), build2 (code, integer_type_node, TREE_OPERAND (loc, 0), TREE_OPERAND (loc, 1)), - TREE_OPERAND (loc, 1), TREE_OPERAND (loc, 0)); + TREE_OPERAND (loc, 1), TREE_OPERAND (loc, 0)); } /* ... fall through ... */ @@ -9195,12 +9206,12 @@ loc_descriptor_from_tree (tree loc, int addressp) case COND_EXPR: { dw_loc_descr_ref lhs - = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0); + = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 1), 0); dw_loc_descr_ref rhs - = loc_descriptor_from_tree (TREE_OPERAND (loc, 2), 0); + = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 2), 0); dw_loc_descr_ref bra_node, jump_node, tmp; - ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0); + ret = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 0); if (ret == 0 || lhs == 0 || rhs == 0) return 0; @@ -9236,11 +9247,11 @@ loc_descriptor_from_tree (tree loc, int addressp) } /* Show if we can't fill the request for an address. */ - if (addressp && indirect_p == 0) + if (want_address && !have_address) return 0; /* If we've got an address and don't want one, dereference. */ - if (!addressp && indirect_p > 0) + if (!want_address && have_address) { HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (loc)); @@ -9257,6 +9268,12 @@ loc_descriptor_from_tree (tree loc, int addressp) return ret; } +static inline dw_loc_descr_ref +loc_descriptor_from_tree (tree loc) +{ + return loc_descriptor_from_tree_1 (loc, 2); +} + /* Given a value, round it up to the lowest multiple of `boundary' which is not less than the value itself. */ @@ -10072,72 +10089,15 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl, } rtl = rtl_for_decl_location (decl); - if (rtl == NULL_RTX) - return; - - switch (GET_CODE (rtl)) + if (rtl && (CONSTANT_P (rtl) || GET_CODE (rtl) == CONST_STRING)) { - case CONST_INT: - case CONST_DOUBLE: - case CONST_VECTOR: - case CONST_STRING: - case SYMBOL_REF: - case LABEL_REF: - case CONST: - case PLUS: - /* DECL_RTL could be (plus (reg ...) (const_int ...)) */ add_const_value_attribute (die, rtl); - break; - - case MEM: - if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl)) - { - /* Need loc_descriptor_from_tree since that's where we know - how to handle TLS variables. Want the object's address - since the top-level DW_AT_location assumes such. See - the confusion in loc_descriptor for reference. */ - descr = loc_descriptor_from_tree (decl, 1); - } - else - { - case REG: - case SUBREG: - case CONCAT: - descr = loc_descriptor (rtl, true); - } - add_AT_location_description (die, attr, descr); - break; - - case PARALLEL: - { - rtvec par_elems = XVEC (rtl, 0); - int num_elem = GET_NUM_ELEM (par_elems); - enum machine_mode mode; - int i; - - /* Create the first one, so we have something to add to. */ - descr = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0), true); - mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0)); - add_loc_descr (&descr, - new_loc_descr (DW_OP_piece, GET_MODE_SIZE (mode), 0)); - for (i = 1; i < num_elem; i++) - { - dw_loc_descr_ref temp; - - temp = loc_descriptor (XEXP (RTVEC_ELT (par_elems, i), 0), true); - add_loc_descr (&descr, temp); - mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0)); - add_loc_descr (&descr, - new_loc_descr (DW_OP_piece, - GET_MODE_SIZE (mode), 0)); - } - } - add_AT_location_description (die, DW_AT_location, descr); - break; - - default: - abort (); + return; } + + descr = loc_descriptor_from_tree (decl); + if (descr) + add_AT_location_description (die, attr, descr); } /* If we don't have a copy of this variable in memory for some reason (such @@ -10254,7 +10214,7 @@ add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, tree b dw_die_ref ctx, decl_die; dw_loc_descr_ref loc; - loc = loc_descriptor_from_tree (bound, 0); + loc = loc_descriptor_from_tree (bound); if (loc == NULL) break; @@ -11388,7 +11348,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) if (cfun->static_chain_decl) add_AT_location_description (subr_die, DW_AT_static_link, - loc_descriptor_from_tree (cfun->static_chain_decl, 0)); + loc_descriptor_from_tree (cfun->static_chain_decl)); } /* Now output descriptions of the arguments for this function. This gets diff --git a/gcc/expr.c b/gcc/expr.c index 7741830033e..282bb9af57d 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -6008,20 +6008,8 @@ expand_var (tree var) ? !TREE_ASM_WRITTEN (var) : !DECL_RTL_SET_P (var)) { - if (TREE_CODE (var) == VAR_DECL && DECL_DEFER_OUTPUT (var)) - { - /* Prepare a mem & address for the decl. */ - rtx x; - - if (TREE_STATIC (var)) - abort (); - - x = gen_rtx_MEM (DECL_MODE (var), - gen_reg_rtx (Pmode)); - - set_mem_attributes (x, var, 1); - SET_DECL_RTL (var, x); - } + if (TREE_CODE (var) == VAR_DECL && DECL_VALUE_EXPR (var)) + /* Should be ignored. */; else if (lang_hooks.expand_decl (var)) /* OK. */; else if (TREE_CODE (var) == VAR_DECL && !TREE_STATIC (var)) diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 1dd0bc32d02..b45197dd191 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,10 @@ +2004-08-10 Richard Henderson + + * f95-lang.c (gfc_init_builtin_functions): Remove + __builtin_stack_alloc, add __builtin_alloca. + * trans-array.c (gfc_trans_auto_array_allocation): Use DECL_EXPR. + * trans-decl.c (gfc_trans_auto_character_variable): Likewise. + 2004-08-10 Paul Brook * trans-io.c (transfer_expr): Handle pointters. diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c index 78bf19a924b..3e8320c3f44 100644 --- a/gcc/fortran/f95-lang.c +++ b/gcc/fortran/f95-lang.c @@ -794,21 +794,23 @@ gfc_init_builtin_functions (void) gfc_define_builtin ("__builtin_adjust_trampoline", ftype, BUILT_IN_ADJUST_TRAMPOLINE, "adjust_trampoline", true); - tmp = tree_cons (NULL_TREE, pvoid_type_node, void_list_node); - tmp = tree_cons (NULL_TREE, size_type_node, void_list_node); - ftype = build_function_type (pvoid_type_node, tmp); - gfc_define_builtin ("__builtin_stack_alloc", ftype, BUILT_IN_STACK_ALLOC, - "stack_alloc", false); + /* The stack_save, stack_restore, and alloca builtins aren't used directly. + They are inserted during gimplification to implement variable sized + stack allocation. */ - /* The stack_save and stack_restore builtins aren't used directly. They - are inserted during gimplification to implement stack_alloc calls. */ ftype = build_function_type (pvoid_type_node, void_list_node); gfc_define_builtin ("__builtin_stack_save", ftype, BUILT_IN_STACK_SAVE, "stack_save", false); + tmp = tree_cons (NULL_TREE, pvoid_type_node, void_list_node); ftype = build_function_type (void_type_node, tmp); gfc_define_builtin ("__builtin_stack_restore", ftype, BUILT_IN_STACK_RESTORE, "stack_restore", false); + + tmp = tree_cons (NULL_TREE, size_type_node, void_list_node); + ftype = build_function_type (pvoid_type_node, tmp); + gfc_define_builtin ("__builtin_alloca", ftype, BUILT_IN_ALLOCA, + "alloca", false); } #undef DEFINE_MATH_BUILTIN diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c index bc825bb00cf..e267ebf2287 100644 --- a/gcc/fortran/trans-array.c +++ b/gcc/fortran/trans-array.c @@ -2926,15 +2926,9 @@ gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym, tree fnbody) { gfc_trans_init_string_length (sym->ts.cl, &block); - DECL_DEFER_OUTPUT (decl) = 1; - - /* Generate code to allocate the automatic variable. It will be - freed automatically. */ - tmp = gfc_build_addr_expr (NULL, decl); - args = gfc_chainon_list (NULL_TREE, tmp); - args = gfc_chainon_list (args, sym->ts.cl->backend_decl); - tmp = gfc_build_function_call (built_in_decls[BUILT_IN_STACK_ALLOC], - args); + /* Emit a DECL_EXPR for this variable, which will cause the + gimplifier to allocate stoage, and all that good stuff. */ + tmp = build (DECL_EXPR, TREE_TYPE (decl), decl); gfc_add_expr_to_block (&block, tmp); } diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c index 5c68cb57348..4710e150fa0 100644 --- a/gcc/fortran/trans-decl.c +++ b/gcc/fortran/trans-decl.c @@ -1626,7 +1626,6 @@ gfc_trans_auto_character_variable (gfc_symbol * sym, tree fnbody) { stmtblock_t body; tree decl; - tree args; tree tmp; assert (sym->backend_decl); @@ -1639,23 +1638,11 @@ gfc_trans_auto_character_variable (gfc_symbol * sym, tree fnbody) decl = sym->backend_decl; - DECL_DEFER_OUTPUT (decl) = 1; - - /* Since we don't use a DECL_STMT or equivalent, we have to deal - with getting these gimplified. But we can't gimplify it yet since - we're still generating statements. - - ??? This should be cleaned up and handled like other front ends. */ - gfc_add_expr_to_block (&body, save_expr (DECL_SIZE (decl))); - gfc_add_expr_to_block (&body, save_expr (DECL_SIZE_UNIT (decl))); - - /* Generate code to allocate the automatic variable. It will be freed - automatically. */ - tmp = gfc_build_addr_expr (NULL, decl); - args = gfc_chainon_list (NULL_TREE, tmp); - args = gfc_chainon_list (args, sym->ts.cl->backend_decl); - tmp = gfc_build_function_call (built_in_decls[BUILT_IN_STACK_ALLOC], args); + /* Emit a DECL_EXPR for this variable, which will cause the + gimplifier to allocate stoage, and all that good stuff. */ + tmp = build (DECL_EXPR, TREE_TYPE (decl), decl); gfc_add_expr_to_block (&body, tmp); + gfc_add_expr_to_block (&body, fnbody); return gfc_finish_block (&body); } diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 3675c8a942f..8a8679b54de 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -976,20 +976,34 @@ gimplify_decl_expr (tree *stmt_p) /* This is a variable-sized decl. Simplify its size and mark it for deferred expansion. Note that mudflap depends on the format of the emitted code: see mx_register_decls(). */ - tree t, args; + tree t, args, addr, ptr_type; gimplify_type_sizes (TREE_TYPE (decl), stmt_p); gimplify_one_sizepos (&DECL_SIZE (decl), stmt_p); gimplify_one_sizepos (&DECL_SIZE_UNIT (decl), stmt_p); + /* All occurences of this decl in final gimplified code will be + replaced by indirection. Setting DECL_VALUE_EXPR does two + things: First, it lets the rest of the gimplifier know what + replacement to use. Second, it lets the debug info know + where to find the value. */ + ptr_type = build_pointer_type (TREE_TYPE (decl)); + addr = create_tmp_var (ptr_type, get_name (decl)); + DECL_IGNORED_P (addr) = 0; + t = build_fold_indirect_ref (addr); + DECL_VALUE_EXPR (decl) = t; + args = tree_cons (NULL, DECL_SIZE_UNIT (decl), NULL); - t = build_fold_addr_expr (decl); - args = tree_cons (NULL, t, args); - t = implicit_built_in_decls[BUILT_IN_STACK_ALLOC]; + t = built_in_decls[BUILT_IN_ALLOCA]; t = build_function_call_expr (t, args); + t = fold_convert (ptr_type, t); + t = build2 (MODIFY_EXPR, void_type_node, addr, t); gimplify_and_add (t, stmt_p); - DECL_DEFER_OUTPUT (decl) = 1; + + /* Indicate that we need to restore the stack level when the + enclosing BIND_EXPR is exited. */ + gimplify_ctxp->save_stack = true; } if (init && init != error_mark_node) @@ -1834,20 +1848,7 @@ gimplify_call_expr (tree *expr_p, tree *pre_p, bool want_value) decl = get_callee_fndecl (*expr_p); if (decl && DECL_BUILT_IN (decl)) { - tree new; - - /* If it is allocation of stack, record the need to restore the memory - when the enclosing bind_expr is exited. */ - if (DECL_FUNCTION_CODE (decl) == BUILT_IN_STACK_ALLOC) - gimplify_ctxp->save_stack = true; - - /* If it is restore of the stack, reset it, since it means we are - regimplifying the bind_expr. Note that we use the fact that - for try_finally_expr, try part is processed first. */ - if (DECL_FUNCTION_CODE (decl) == BUILT_IN_STACK_RESTORE) - gimplify_ctxp->save_stack = false; - - new = simplify_builtin (*expr_p, !want_value); + tree new = simplify_builtin (*expr_p, !want_value); if (new && new != *expr_p) { @@ -3781,9 +3782,19 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p, abort (); #endif ret = GS_ERROR; + break; } - else - ret = GS_ALL_DONE; + + /* If this is a local variable sized decl, it must be accessed + indirectly. Perform that substitution. */ + if (DECL_VALUE_EXPR (tmp)) + { + *expr_p = unshare_expr (DECL_VALUE_EXPR (tmp)); + ret = GS_OK; + break; + } + + ret = GS_ALL_DONE; break; case SSA_NAME: diff --git a/gcc/stmt.c b/gcc/stmt.c index 8164c2d269f..86d4fe98dd3 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -2042,40 +2042,6 @@ expand_decl (tree decl) } } -/* Emit code to allocate T_SIZE bytes of dynamic stack space for ALLOC. */ -void -expand_stack_alloc (tree alloc, tree t_size) -{ - rtx address, dest, size; - tree var, type; - - if (TREE_CODE (alloc) != ADDR_EXPR) - abort (); - var = TREE_OPERAND (alloc, 0); - if (TREE_CODE (var) != VAR_DECL) - abort (); - - type = TREE_TYPE (var); - - /* Compute the variable's size, in bytes. */ - size = expand_expr (t_size, NULL_RTX, VOIDmode, 0); - free_temp_slots (); - - /* Allocate space on the stack for the variable. */ - address = XEXP (DECL_RTL (var), 0); - dest = allocate_dynamic_stack_space (size, address, TYPE_ALIGN (type)); - if (dest != address) - emit_move_insn (address, dest); - - /* Indicate the alignment we actually gave this variable. */ -#ifdef STACK_BOUNDARY - DECL_ALIGN (var) = STACK_BOUNDARY; -#else - DECL_ALIGN (var) = BIGGEST_ALIGNMENT; -#endif - DECL_USER_ALIGN (var) = 0; -} - /* Emit code to save the current value of stack. */ rtx expand_stack_save (void) diff --git a/gcc/tree-mudflap.c b/gcc/tree-mudflap.c index bd176200530..4f8e1742f2d 100644 --- a/gcc/tree-mudflap.c +++ b/gcc/tree-mudflap.c @@ -897,6 +897,8 @@ mx_register_decls (tree decl, tree *stmt_list) && TREE_ADDRESSABLE (decl) /* The type of the variable must be complete. */ && COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (decl)) + /* The decl hasn't been decomposed somehow. */ + && DECL_VALUE_EXPR (decl) == NULL /* Don't process the same decl twice. */ && ! mf_marked_p (decl)) { @@ -904,73 +906,7 @@ mx_register_decls (tree decl, tree *stmt_list) tree unregister_fncall, unregister_fncall_params; tree register_fncall, register_fncall_params; - if (DECL_DEFER_OUTPUT (decl)) - { - /* Oh no ... it's probably a variable-length array (VLA). - The size and address cannot be computed by merely - looking at the DECL. See gimplify_decl_stmt for the - method by which VLA declarations turn into calls to - BUILT_IN_STACK_ALLOC. We assume that multiple - VLAs declared later in the same block get allocation - code later than the others. */ - tree stack_alloc_call = NULL_TREE; - - while(! tsi_end_p (initially_stmts)) - { - tree t = tsi_stmt (initially_stmts); - - tree call = NULL_TREE; - if (TREE_CODE (t) == CALL_EXPR) - call = t; - else if (TREE_CODE (t) == MODIFY_EXPR && - TREE_CODE (TREE_OPERAND (t, 1)) == CALL_EXPR) - call = TREE_OPERAND (t, 1); - else if (TREE_CODE (t) == TRY_FINALLY_EXPR) - { - /* We hope that this is the try/finally block sometimes - constructed by gimplify_bind_expr() for a BIND_EXPR - that contains VLAs. This very naive recursion - appears to be sufficient. */ - initially_stmts = tsi_start (TREE_OPERAND (t, 0)); - } - - if (call != NULL_TREE) - { - if (TREE_CODE (TREE_OPERAND(call, 0)) == ADDR_EXPR && - TREE_OPERAND (TREE_OPERAND (call, 0), 0) == - implicit_built_in_decls [BUILT_IN_STACK_ALLOC]) - { - tree stack_alloc_args = TREE_OPERAND (call, 1); - tree stack_alloc_op1 = TREE_VALUE (stack_alloc_args); - tree stack_alloc_op2 = TREE_VALUE (TREE_CHAIN (stack_alloc_args)); - - if (TREE_CODE (stack_alloc_op1) == ADDR_EXPR && - TREE_OPERAND (stack_alloc_op1, 0) == decl) - { - /* Got it! */ - size = stack_alloc_op2; - stack_alloc_call = call; - /* Advance iterator to point past this allocation call. */ - tsi_next (&initially_stmts); - break; - } - } - } - - tsi_next (&initially_stmts); - } - - if (stack_alloc_call == NULL_TREE) - { - warning ("mudflap cannot handle variable-sized declaration `%s'", - IDENTIFIER_POINTER (DECL_NAME (decl))); - break; - } - } - else - { - size = convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (decl))); - } + size = convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (decl))); /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK) */ unregister_fncall_params = diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c index e884260d2b3..7ae506e8558 100644 --- a/gcc/tree-nested.c +++ b/gcc/tree-nested.c @@ -855,7 +855,7 @@ convert_local_reference (tree *tp, int *walk_subtrees, void *data) { struct walk_stmt_info *wi = data; struct nesting_info *info = wi->info; - tree t = *tp, field, x, y; + tree t = *tp, field, x; switch (TREE_CODE (t)) { @@ -909,40 +909,6 @@ convert_local_reference (tree *tp, int *walk_subtrees, void *data) } break; - case CALL_EXPR: - *walk_subtrees = 1; - - /* Ready for some fun? We need to recognize - __builtin_stack_alloc (&x, n) - and insert - FRAME.x = &x - after that. X should have use_pointer_in_frame set. We can't - do this any earlier, since we can't meaningfully evaluate &x. */ - - x = get_callee_fndecl (t); - if (!x || DECL_BUILT_IN_CLASS (x) != BUILT_IN_NORMAL) - break; - if (DECL_FUNCTION_CODE (x) != BUILT_IN_STACK_ALLOC) - break; - t = TREE_VALUE (TREE_OPERAND (t, 1)); - if (TREE_CODE (t) != ADDR_EXPR) - abort (); - t = TREE_OPERAND (t, 0); - if (TREE_CODE (t) != VAR_DECL) - abort (); - field = lookup_field_for_decl (info, t, NO_INSERT); - if (!field) - break; - if (!use_pointer_in_frame (t)) - abort (); - - x = build_addr (t); - y = get_frame_field (info, info->context, field, &wi->tsi); - x = build (MODIFY_EXPR, void_type_node, y, x); - SET_EXPR_LOCUS (x, EXPR_LOCUS (tsi_stmt (wi->tsi))); - tsi_link_after (&wi->tsi, x, TSI_SAME_STMT); - break; - case REALPART_EXPR: case IMAGPART_EXPR: case COMPONENT_REF: diff --git a/gcc/tree.h b/gcc/tree.h index a75a0ea23db..0d6d5608310 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -2027,6 +2027,13 @@ struct tree_binfo GTY (()) entire function. */ #define DECL_SAVED_TREE(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.saved_tree) +/* In a VAR_DECL or PARM_DECL, the location at which the value may be found, + if transformations have made this more complicated than evaluating the + decl itself. This should only be used for debugging; once this field has + been set, the decl itself may not legitimately appear in the function. */ +#define DECL_VALUE_EXPR(NODE) \ + (TREE_CHECK2 (NODE, VAR_DECL, PARM_DECL)->decl.saved_tree) + /* List of FUNCTION_DECLs inlined into this function's body. */ #define DECL_INLINED_FNS(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.inlined_fns) @@ -2278,7 +2285,8 @@ struct tree_decl GTY(()) int GTY ((tag ("VAR_DECL"))) i; } GTY ((desc ("TREE_CODE((tree) &(%0))"))) u2; - /* In a FUNCTION_DECL, this is DECL_SAVED_TREE. */ + /* In a FUNCTION_DECL, this is DECL_SAVED_TREE. + In a VAR_DECL or PARM_DECL, this is DECL_VALUE_EXPR. */ tree saved_tree; /* In a FUNCTION_DECL, these are function data which is to be kept @@ -3353,7 +3361,6 @@ extern void expand_label (tree); extern void expand_goto (tree); extern void expand_asm (tree, int); -extern void expand_stack_alloc (tree, tree); extern rtx expand_stack_save (void); extern void expand_stack_restore (tree); extern void expand_return (tree);