Commit 38afb23f by Olivier Hainque Committed by Richard Kenner

calls.c (expand_call): Move special case for constructor calls to right place.

	* calls.c (expand_call): Move special case for constructor calls
	to right place. Ensures constructor calls used to initialize
	arguments get a clean outgoing argument block for themselves.
	Move check for stack deallocation completeness until after last
	deallocation.  Add stack_pointer_delta to set of state
	variables saved and restored along with current stack_level.

From-SVN: r65795
parent e59baa1f
2003-04-18 Olivier Hainque <hainque@act-europe.fr> 2003-04-18 Olivier Hainque <hainque@act-europe.fr>
* calls.c (expand_call): Move special case for constructor calls
to right place. Ensures constructor calls used to initialize
arguments get a clean outgoing argument block for themselves.
Move check for stack deallocation completeness until after last
deallocation. Add stack_pointer_delta to set of state
variables saved and restored along with current stack_level.
* integrate.c (expand_inline_function): Ensure non-const actuals * integrate.c (expand_inline_function): Ensure non-const actuals
don't end up const in the caller's flow after conversion to possibly don't end up const in the caller's flow after conversion to possibly
const formal type. const formal type.
......
...@@ -2200,12 +2200,20 @@ expand_call (exp, target, ignore) ...@@ -2200,12 +2200,20 @@ expand_call (exp, target, ignore)
int initial_highest_arg_in_use = highest_outgoing_arg_in_use; int initial_highest_arg_in_use = highest_outgoing_arg_in_use;
char *initial_stack_usage_map = stack_usage_map; char *initial_stack_usage_map = stack_usage_map;
int old_stack_arg_under_construction = 0;
int old_stack_allocated;
/* State variables to track stack modifications. */
rtx old_stack_level = 0; rtx old_stack_level = 0;
int old_stack_arg_under_construction = 0;
int old_pending_adj = 0; int old_pending_adj = 0;
int old_inhibit_defer_pop = inhibit_defer_pop; int old_inhibit_defer_pop = inhibit_defer_pop;
int old_stack_allocated;
/* Some stack pointer alterations we make are performed via
allocate_dynamic_stack_space. This modifies the stack_pointer_delta,
which we then also need to save/restore along the way. */
int old_stack_pointer_delta;
rtx call_fusage; rtx call_fusage;
tree p = TREE_OPERAND (exp, 0); tree p = TREE_OPERAND (exp, 0);
tree addr = TREE_OPERAND (exp, 0); tree addr = TREE_OPERAND (exp, 0);
...@@ -2751,6 +2759,7 @@ expand_call (exp, target, ignore) ...@@ -2751,6 +2759,7 @@ expand_call (exp, target, ignore)
if (old_stack_level == 0) if (old_stack_level == 0)
{ {
emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX); emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX);
old_stack_pointer_delta = stack_pointer_delta;
old_pending_adj = pending_stack_adjust; old_pending_adj = pending_stack_adjust;
pending_stack_adjust = 0; pending_stack_adjust = 0;
/* stack_arg_under_construction says whether a stack arg is /* stack_arg_under_construction says whether a stack arg is
...@@ -2877,53 +2886,58 @@ expand_call (exp, target, ignore) ...@@ -2877,53 +2886,58 @@ expand_call (exp, target, ignore)
VIRTUAL_OUTGOING_ARGS_RTX changes as well. But might VIRTUAL_OUTGOING_ARGS_RTX changes as well. But might
as well always do it. */ as well always do it. */
argblock = copy_to_reg (argblock); argblock = copy_to_reg (argblock);
}
}
}
/* The save/restore code in store_one_arg handles all if (ACCUMULATE_OUTGOING_ARGS)
cases except one: a constructor call (including a C {
function returning a BLKmode struct) to initialize /* The save/restore code in store_one_arg handles all
an argument. */ cases except one: a constructor call (including a C
if (stack_arg_under_construction) function returning a BLKmode struct) to initialize
{ an argument. */
if (stack_arg_under_construction)
{
#ifndef OUTGOING_REG_PARM_STACK_SPACE #ifndef OUTGOING_REG_PARM_STACK_SPACE
rtx push_size = GEN_INT (reg_parm_stack_space rtx push_size = GEN_INT (reg_parm_stack_space
+ adjusted_args_size.constant); + adjusted_args_size.constant);
#else #else
rtx push_size = GEN_INT (adjusted_args_size.constant); rtx push_size = GEN_INT (adjusted_args_size.constant);
#endif #endif
if (old_stack_level == 0) if (old_stack_level == 0)
{ {
emit_stack_save (SAVE_BLOCK, &old_stack_level, emit_stack_save (SAVE_BLOCK, &old_stack_level,
NULL_RTX); NULL_RTX);
old_pending_adj = pending_stack_adjust; old_stack_pointer_delta = stack_pointer_delta;
pending_stack_adjust = 0; old_pending_adj = pending_stack_adjust;
/* stack_arg_under_construction says whether a stack pending_stack_adjust = 0;
arg is being constructed at the old stack level. /* stack_arg_under_construction says whether a stack
Pushing the stack gets a clean outgoing argument arg is being constructed at the old stack level.
block. */ Pushing the stack gets a clean outgoing argument
old_stack_arg_under_construction block. */
= stack_arg_under_construction; old_stack_arg_under_construction
stack_arg_under_construction = 0; = stack_arg_under_construction;
/* Make a new map for the new argument list. */ stack_arg_under_construction = 0;
stack_usage_map = (char *) /* Make a new map for the new argument list. */
alloca (highest_outgoing_arg_in_use); stack_usage_map = (char *)
memset (stack_usage_map, 0, highest_outgoing_arg_in_use); alloca (highest_outgoing_arg_in_use);
highest_outgoing_arg_in_use = 0; memset (stack_usage_map, 0, highest_outgoing_arg_in_use);
} highest_outgoing_arg_in_use = 0;
allocate_dynamic_stack_space (push_size, NULL_RTX,
BITS_PER_UNIT);
}
/* If argument evaluation might modify the stack pointer,
copy the address of the argument list to a register. */
for (i = 0; i < num_actuals; i++)
if (args[i].pass_on_stack)
{
argblock = copy_addr_to_reg (argblock);
break;
}
} }
allocate_dynamic_stack_space (push_size, NULL_RTX,
BITS_PER_UNIT);
} }
}
/* If argument evaluation might modify the stack pointer,
copy the address of the argument list to a register. */
for (i = 0; i < num_actuals; i++)
if (args[i].pass_on_stack)
{
argblock = copy_addr_to_reg (argblock);
break;
}
}
compute_argument_addresses (args, argblock, num_actuals); compute_argument_addresses (args, argblock, num_actuals);
/* If we push args individually in reverse order, perform stack alignment /* If we push args individually in reverse order, perform stack alignment
...@@ -3087,11 +3101,6 @@ expand_call (exp, target, ignore) ...@@ -3087,11 +3101,6 @@ expand_call (exp, target, ignore)
next_arg_reg, valreg, old_inhibit_defer_pop, call_fusage, next_arg_reg, valreg, old_inhibit_defer_pop, call_fusage,
flags, & args_so_far); flags, & args_so_far);
/* Verify that we've deallocated all the stack we used. */
if (pass
&& old_stack_allocated != stack_pointer_delta - pending_stack_adjust)
abort ();
/* If call is cse'able, make appropriate pair of reg-notes around it. /* If call is cse'able, make appropriate pair of reg-notes around it.
Test valreg so we don't crash; may safely ignore `const' Test valreg so we don't crash; may safely ignore `const'
if return type is void. Disable for PARALLEL return values, because if return type is void. Disable for PARALLEL return values, because
...@@ -3313,6 +3322,7 @@ expand_call (exp, target, ignore) ...@@ -3313,6 +3322,7 @@ expand_call (exp, target, ignore)
if (old_stack_level && ! (flags & ECF_SP_DEPRESSED)) if (old_stack_level && ! (flags & ECF_SP_DEPRESSED))
{ {
emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX); emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
stack_pointer_delta = old_stack_pointer_delta;
pending_stack_adjust = old_pending_adj; pending_stack_adjust = old_pending_adj;
stack_arg_under_construction = old_stack_arg_under_construction; stack_arg_under_construction = old_stack_arg_under_construction;
highest_outgoing_arg_in_use = initial_highest_arg_in_use; highest_outgoing_arg_in_use = initial_highest_arg_in_use;
...@@ -3393,7 +3403,14 @@ expand_call (exp, target, ignore) ...@@ -3393,7 +3403,14 @@ expand_call (exp, target, ignore)
sbitmap_free (stored_args_map); sbitmap_free (stored_args_map);
} }
else else
normal_call_insns = insns; {
normal_call_insns = insns;
/* Verify that we've deallocated all the stack we used. */
if (old_stack_allocated !=
stack_pointer_delta - pending_stack_adjust)
abort ();
}
/* If something prevents making this a sibling call, /* If something prevents making this a sibling call,
zero out the sequence. */ zero out the sequence. */
......
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