This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH , rs6000] Fix order of prologue instructions for varargs functions with -O0 and -m32
- From: Luis Machado <luisgpm at linux dot vnet dot ibm dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 26 Feb 2009 12:40:21 -0300
- Subject: [PATCH , rs6000] Fix order of prologue instructions for varargs functions with -O0 and -m32
- Reply-to: luisgpm at linux dot vnet dot ibm dot com
Hi,
Considering this little example using varargs for ppc:
void testvad32 (int n, ...)
{
__builtin_va_list ap;
__builtin_va_start (ap, n);
__builtin_va_end (ap);
}
When built with -O0 and -m32, we get the following asm as output:
stw 4,28(31)
stw 5,32(31)
stw 6,36(31)
stw 7,40(31)
stw 8,44(31)
stw 9,48(31)
stw 10,52(31)
>>>>> Debug info tells us r3 is already saved at this point
bne 1,.L2
stfd 1,56(31)
stfd 2,64(31)
stfd 3,72(31)
stfd 4,80(31)
stfd 5,88(31)
stfd 6,96(31)
stfd 7,104(31)
stfd 8,112(31)
>>>>> End of prologue/Beginning of function
stw 3,120(31)
As we can see, r3 isn't saved to the stack until later in the process,
but the debugging information tells us r3 should already be on slot 120
right before the branch instruction. This prevents GDB from getting the
correct value for the last named argument of a variadic function right
upon entering it.
The following patch reorders the statement responsible for generating
varargs-related RTL code. Basically, we'll only generate the RTL code
for unamed parameters after we have the RTL ready for the last named
parameter.
It also does some cleaning on "rs6000.c" since, with the reordering,
there's a variable there that is not relevant anymore.
Bootstrapped and regtested using the testsuite. The results looked OK,
with no changes.
Ok for mainline?
Luis
2009-02-26 Luis Machado <luisgpm@br.ibm.com>
* function.c (assign_parms): Delay generation of varargs-related
RTL code.
* config/rs6000/rs6000.c (setup_incoming_varargs): Remove NEXT_CUM
variable and use CUM instead. Don't skip a parameter.
Index: gcc/function.c
===================================================================
--- gcc.orig/function.c 2009-02-20 11:54:18.000000000 -0600
+++ gcc/function.c 2009-02-25 18:32:09.000000000 -0600
@@ -3122,9 +3122,6 @@
}
}
- if (cfun->stdarg && !TREE_CHAIN (parm))
- assign_parms_setup_varargs (&all, &data, false);
-
/* Find out where the parameter arrives in this function. */
assign_parm_find_entry_rtl (&all, &data);
@@ -3150,6 +3147,10 @@
assign_parm_setup_reg (&all, parm, &data);
else
assign_parm_setup_stack (&all, parm, &data);
+
+ if (cfun->stdarg && !TREE_CHAIN (parm))
+ assign_parms_setup_varargs (&all, &data, false);
+
}
if (targetm.calls.split_complex_arg && fnargs != all.orig_fnargs)
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc.orig/config/rs6000/rs6000.c 2009-02-25 16:09:27.000000000 -0600
+++ gcc/config/rs6000/rs6000.c 2009-02-26 09:04:00.000000000 -0600
@@ -6663,19 +6663,14 @@
tree type, int *pretend_size ATTRIBUTE_UNUSED,
int no_rtl)
{
- CUMULATIVE_ARGS next_cum;
int reg_size = TARGET_32BIT ? 4 : 8;
rtx save_area = NULL_RTX, mem;
int first_reg_offset;
alias_set_type set;
- /* Skip the last named argument. */
- next_cum = *cum;
- function_arg_advance (&next_cum, mode, type, 1, 0);
-
if (DEFAULT_ABI == ABI_V4)
{
- first_reg_offset = next_cum.sysv_gregno - GP_ARG_MIN_REG;
+ first_reg_offset = cum->sysv_gregno - GP_ARG_MIN_REG;
if (! no_rtl)
{
@@ -6690,17 +6685,17 @@
if (cfun->va_list_gpr_size && first_reg_offset < GP_ARG_NUM_REG)
gpr_reg_num = GP_ARG_NUM_REG - first_reg_offset;
if (TARGET_HARD_FLOAT && TARGET_FPRS
- && next_cum.fregno <= FP_ARG_V4_MAX_REG
+ && cum->fregno <= FP_ARG_V4_MAX_REG
&& cfun->va_list_fpr_size)
{
if (gpr_reg_num)
- fpr_size = (next_cum.fregno - FP_ARG_MIN_REG)
+ fpr_size = (cum->fregno - FP_ARG_MIN_REG)
* UNITS_PER_FP_WORD;
if (cfun->va_list_fpr_size
- < FP_ARG_V4_MAX_REG + 1 - next_cum.fregno)
+ < FP_ARG_V4_MAX_REG + 1 - cum->fregno)
fpr_size += cfun->va_list_fpr_size * UNITS_PER_FP_WORD;
else
- fpr_size += (FP_ARG_V4_MAX_REG + 1 - next_cum.fregno)
+ fpr_size += (FP_ARG_V4_MAX_REG + 1 - cum->fregno)
* UNITS_PER_FP_WORD;
}
if (gpr_reg_num)
@@ -6715,7 +6710,7 @@
gpr_size = (gpr_reg_num * reg_size + 7) & ~7;
}
else if (fpr_size)
- offset = - (int) (next_cum.fregno - FP_ARG_MIN_REG)
+ offset = - (int) (cum->fregno - FP_ARG_MIN_REG)
* UNITS_PER_FP_WORD
- (int) (GP_ARG_NUM_REG * reg_size);
@@ -6742,7 +6737,7 @@
}
else
{
- first_reg_offset = next_cum.words;
+ first_reg_offset = cum->words;
save_area = virtual_incoming_args_rtx;
if (targetm.calls.must_pass_in_stack (mode, type))
@@ -6783,10 +6778,10 @@
if (DEFAULT_ABI == ABI_V4
&& TARGET_HARD_FLOAT && TARGET_FPRS
&& ! no_rtl
- && next_cum.fregno <= FP_ARG_V4_MAX_REG
+ && cum->fregno <= FP_ARG_V4_MAX_REG
&& cfun->va_list_fpr_size)
{
- int fregno = next_cum.fregno, nregs;
+ int fregno = cum->fregno, nregs;
rtx cr1 = gen_rtx_REG (CCmode, CR1_REGNO);
rtx lab = gen_label_rtx ();
int off = (GP_ARG_NUM_REG * reg_size) + ((fregno - FP_ARG_MIN_REG)