builtins.def (BUILT_IN_STACK_ALLOC): Remove.

* builtins.def (BUILT_IN_STACK_ALLOC): Remove.
        * builtins.c (expand_builtin) <BUILT_IN_STACK_ALLOC>: 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
This commit is contained in:
Richard Henderson 2004-08-10 21:16:07 -07:00 committed by Richard Henderson
parent 89f1a7022e
commit 1a186ec558
16 changed files with 208 additions and 356 deletions

View File

@ -1,3 +1,26 @@
2004-08-10 Richard Henderson <rth@redhat.com>
* builtins.def (BUILT_IN_STACK_ALLOC): Remove.
* builtins.c (expand_builtin) <BUILT_IN_STACK_ALLOC>: 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 <rth@redhat.com>
* stor-layout.c (round_up): Check for 0/1 before dividing.

View File

@ -1,3 +1,8 @@
2004-08-10 Richard Henderson <rth@redhat.com>
* utils.c (gnat_install_builtins): Remove __builtin_stack_alloc,
add __builtin_alloca.
2004-08-10 Richard Henderson <rth@redhat.com>
* config-lang.in (boot_language): Yes.

View File

@ -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

View File

@ -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 ();

View File

@ -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)

View File

@ -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

View File

@ -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))

View File

@ -1,3 +1,10 @@
2004-08-10 Richard Henderson <rth@redhat.com>
* 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 <paul@codesourcery.com>
* trans-io.c (transfer_expr): Handle pointters.

View File

@ -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

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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:

View File

@ -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)

View File

@ -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 =

View File

@ -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:

View File

@ -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);