On Fri, Jul 17, 2015 at 7:49 PM, H.J. Lu <[email protected]> wrote:
> If we put static chain on the stack, we need to replicate it on the stack
> so that static chain can be reached via (argp - 2) slot. This is needed
> for nested function with stack realignment.
>
> OK for trunk if there are no regressions?
>
> H.J.
> ---
> gcc/
>
> PR target/66906
> * config/i386/i386.c (ix86_expand_prologue): Replicate static
> chain on the stack.
>
> gcc/testsuite/
>
> PR target/66906
> * gcc.target/i386/pr66906.c: New test.
> ---
> gcc/config/i386/i386.c | 18 ++++++++++++-
> gcc/testsuite/gcc.target/i386/pr66906.c | 45
> +++++++++++++++++++++++++++++++++
> 2 files changed, 62 insertions(+), 1 deletion(-)
> create mode 100644 gcc/testsuite/gcc.target/i386/pr66906.c
>
> diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> index 0551a75..3803dde 100644
> --- a/gcc/config/i386/i386.c
> +++ b/gcc/config/i386/i386.c
> @@ -11495,6 +11495,7 @@ ix86_expand_prologue (void)
> HOST_WIDE_INT allocate;
> bool int_registers_saved;
> bool sse_registers_saved;
> + rtx static_chain = NULL_RTX;
>
> ix86_finalize_stack_realign_flags ();
>
> @@ -11593,7 +11594,8 @@ ix86_expand_prologue (void)
> call. This insn will be skipped by the trampoline. */
> else if (ix86_static_chain_on_stack)
> {
> - insn = emit_insn (gen_push (ix86_static_chain (cfun->decl, false)));
> + static_chain = ix86_static_chain (cfun->decl, false);
> + insn = emit_insn (gen_push (static_chain));
> emit_insn (gen_blockage ());
>
> /* We don't want to interpret this push insn as a register save,
> @@ -11645,6 +11647,20 @@ ix86_expand_prologue (void)
> we've started over with a new frame. */
> m->fs.sp_offset = INCOMING_FRAME_SP_OFFSET;
> m->fs.realigned = true;
> +
> + if (static_chain)
> + {
> + /* Replicate static chain on the stack so that static chain
> + can be reached via (argp - 2) slot. This is needed for
> + nested function with stack realignment. */
> + t = plus_constant (Pmode, stack_pointer_rtx, -UNITS_PER_WORD);
> + t = gen_rtx_SET (stack_pointer_rtx, t);
> + insn = emit_insn (t);
> + RTX_FRAME_RELATED_P (insn) = 1;
> + emit_move_insn (gen_rtx_MEM (Pmode, stack_pointer_rtx),
> + static_chain);
> + m->fs.sp_offset += UNITS_PER_WORD;
All above can be just:
if (static_chain)
{
/* ... */
insn = emit_insn (gen_push (static_chain));
RTX_FRAME_RELATED_P (insn) = 1;
}
Please check if the above code survives bootstrap and regression test on x86_32.
Uros.