[NDS32] Emit stack push instructions for varargs at prologue stage and emit...

[NDS32]  Emit stack push instructions for varargs at prologue stage and
         emit stack adjustment instructions for varargs at epilogue stage.

  -- Note that we do not need to handle it in v3push/v3pop prologue/epilogue
     expanding because we do not apply v3push/v3pop for variadic function.

	* config/nds32/nds32.c (nds32_expand_prologue): Emit stack push
	instructions for varargs implementation.
	(nds32_expand_epilogue): Emit stack adjustment instructions for
	varargs implementation.

From-SVN: r214867
This commit is contained in:
Chung-Ju Wu 2014-09-03 10:09:14 +00:00 committed by Chung-Ju Wu
parent 99575d60c8
commit 557430f169
2 changed files with 87 additions and 1 deletions

View file

@ -1,3 +1,10 @@
2014-09-03 Chung-Ju Wu <jasonwucj@gmail.com>
* config/nds32/nds32.c (nds32_expand_prologue): Emit stack push
instructions for varargs implementation.
(nds32_expand_epilogue): Emit stack adjustment instructions for
varargs implementation.
2014-09-03 Chung-Ju Wu <jasonwucj@gmail.com>
* config/nds32/nds32.c (nds32_expand_prologue): Suppress fp-as-gp

View file

@ -2788,6 +2788,35 @@ nds32_expand_prologue (void)
The result will be in cfun->machine. */
nds32_compute_stack_frame ();
/* If this is a variadic function, first we need to push argument
registers that hold the unnamed argument value. */
if (cfun->machine->va_args_size != 0)
{
Rb = gen_rtx_REG (SImode, cfun->machine->va_args_first_regno);
Re = gen_rtx_REG (SImode, cfun->machine->va_args_last_regno);
/* No need to push $fp, $gp, or $lp, so use GEN_INT(0). */
nds32_emit_stack_push_multiple (Rb, Re, GEN_INT (0));
/* We may also need to adjust stack pointer for padding bytes
because varargs may cause $sp not 8-byte aligned. */
if (cfun->machine->va_args_area_padding_bytes)
{
/* Generate sp adjustment instruction. */
sp_adjust = cfun->machine->va_args_area_padding_bytes;
sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
stack_pointer_rtx,
GEN_INT (-1 * sp_adjust));
/* Emit rtx into instructions list and receive INSN rtx form. */
sp_adjust_insn = emit_insn (sp_adjust_insn);
/* The insn rtx 'sp_adjust_insn' will change frame layout.
We need to use RTX_FRAME_RELATED_P so that GCC is able to
generate CFI (Call Frame Information) stuff. */
RTX_FRAME_RELATED_P (sp_adjust_insn) = 1;
}
}
/* If the function is 'naked',
we do not have to generate prologue code fragment. */
if (cfun->machine->naked_p)
@ -2887,9 +2916,32 @@ nds32_expand_epilogue (void)
emit_insn (gen_blockage ());
/* If the function is 'naked', we do not have to generate
epilogue code fragment BUT 'ret' instruction. */
epilogue code fragment BUT 'ret' instruction.
However, if this function is also a variadic function,
we need to create adjust stack pointer before 'ret' instruction. */
if (cfun->machine->naked_p)
{
/* If this is a variadic function, we do not have to restore argument
registers but need to adjust stack pointer back to previous stack
frame location before return. */
if (cfun->machine->va_args_size != 0)
{
/* Generate sp adjustment instruction.
We need to consider padding bytes here. */
sp_adjust = cfun->machine->va_args_size
+ cfun->machine->va_args_area_padding_bytes;
sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
stack_pointer_rtx,
GEN_INT (sp_adjust));
/* Emit rtx into instructions list and receive INSN rtx form. */
sp_adjust_insn = emit_insn (sp_adjust_insn);
/* The insn rtx 'sp_adjust_insn' will change frame layout.
We need to use RTX_FRAME_RELATED_P so that GCC is able to
generate CFI (Call Frame Information) stuff. */
RTX_FRAME_RELATED_P (sp_adjust_insn) = 1;
}
/* Generate return instruction by using
unspec_volatile_func_return pattern.
Make sure this instruction is after gen_blockage().
@ -2916,6 +2968,9 @@ nds32_expand_epilogue (void)
GEN_INT (-1 * sp_adjust));
/* Emit rtx into instructions list and receive INSN rtx form. */
sp_adjust_insn = emit_insn (sp_adjust_insn);
/* The insn rtx 'sp_adjust_insn' will change frame layout. */
RTX_FRAME_RELATED_P (sp_adjust_insn) = 1;
}
else
{
@ -2944,6 +2999,9 @@ nds32_expand_epilogue (void)
GEN_INT (sp_adjust));
/* Emit rtx into instructions list and receive INSN rtx form. */
sp_adjust_insn = emit_insn (sp_adjust_insn);
/* The insn rtx 'sp_adjust_insn' will change frame layout. */
RTX_FRAME_RELATED_P (sp_adjust_insn) = 1;
}
}
@ -2972,6 +3030,27 @@ nds32_expand_epilogue (void)
nds32_emit_stack_pop_multiple (Rb, Re, GEN_INT (en4_const));
}
/* If this is a variadic function, we do not have to restore argument
registers but need to adjust stack pointer back to previous stack
frame location before return. */
if (cfun->machine->va_args_size != 0)
{
/* Generate sp adjustment instruction.
We need to consider padding bytes here. */
sp_adjust = cfun->machine->va_args_size
+ cfun->machine->va_args_area_padding_bytes;
sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
stack_pointer_rtx,
GEN_INT (sp_adjust));
/* Emit rtx into instructions list and receive INSN rtx form. */
sp_adjust_insn = emit_insn (sp_adjust_insn);
/* The insn rtx 'sp_adjust_insn' will change frame layout.
We need to use RTX_FRAME_RELATED_P so that GCC is able to
generate CFI (Call Frame Information) stuff. */
RTX_FRAME_RELATED_P (sp_adjust_insn) = 1;
}
/* Generate return instruction by using
unspec_volatile_func_return pattern. */
emit_insn (gen_unspec_volatile_func_return ());