Commit 1a186ec5 by Richard Henderson Committed by Richard Henderson

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
parent 89f1a702
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.
(round_down): Likewise.
......
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.
2004-08-09 Thomas Quinot <quinot@act-europe.fr>
......
......@@ -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
......
......@@ -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 ();
......
......@@ -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)
......
......@@ -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))
......
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.
......
......@@ -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
......
......@@ -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);
}
......
......@@ -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);
}
......
......@@ -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:
......
......@@ -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)
......
......@@ -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 =
......
......@@ -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:
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment