From 557430f1699f0ad881815957f35fdc9b11a09608 Mon Sep 17 00:00:00 2001 From: Chung-Ju Wu Date: Wed, 3 Sep 2014 10:09:14 +0000 Subject: [PATCH] [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 --- gcc/ChangeLog | 7 ++++ gcc/config/nds32/nds32.c | 81 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 87 insertions(+), 1 deletion(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index aaeea0a7647..26e89f6762b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2014-09-03 Chung-Ju Wu + + * 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 * config/nds32/nds32.c (nds32_expand_prologue): Suppress fp-as-gp diff --git a/gcc/config/nds32/nds32.c b/gcc/config/nds32/nds32.c index d76d8251db3..d2890dc3d27 100644 --- a/gcc/config/nds32/nds32.c +++ b/gcc/config/nds32/nds32.c @@ -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 ()); -- 2.30.2