diff options
author | Jozef Lawrynowicz <jozef.l@mittosystems.com> | 2020-09-18 13:03:13 +0100 |
---|---|---|
committer | Jozef Lawrynowicz <jozef.l@mittosystems.com> | 2020-09-18 13:03:13 +0100 |
commit | 685c95ebc4906f6b58db2e3c81ad9ab73fdca794 (patch) | |
tree | f88db1c197d7e1f28908a7977405180bfdbda918 /gcc/config/msp430 | |
parent | 220724c311473b8b0f2418350c2b64e796e92bda (diff) | |
download | gcc-685c95ebc4906f6b58db2e3c81ad9ab73fdca794.zip gcc-685c95ebc4906f6b58db2e3c81ad9ab73fdca794.tar.gz gcc-685c95ebc4906f6b58db2e3c81ad9ab73fdca794.tar.bz2 |
MSP430: Fix CFA generation during function epilogues
There is no CFA information generated for instructions that manipulate the
stack during function epilogues. This means a debugger cannot determine the
position of variables on the stack whilst the epilogue is in progress.
This can cause the debugger to give erroneous information when printing a
backtrace whilst stepping through the epilogue, or cause software watchpoints
set on stack variables to become invalidated after a function epilogue
is executed.
The patch fixes this by marking stack manipulation insns as
frame_related, and adding reg_note RTXs to stack pop instructions in the
epilogue.
gcc/ChangeLog:
* config/msp430/msp430.c (increment_stack): Mark insns which increment
the stack as frame_related.
(msp430_expand_prologue): Add comments.
(msp430_expand_epilogue): Mark insns which decrement
the stack as frame_related.
Add reg_note to stack pop insns describing position of register
variables on the stack.
Diffstat (limited to 'gcc/config/msp430')
-rw-r--r-- | gcc/config/msp430/msp430.c | 72 |
1 files changed, 59 insertions, 13 deletions
diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c index a299ed7..68a67bd 100644 --- a/gcc/config/msp430/msp430.c +++ b/gcc/config/msp430/msp430.c @@ -1695,9 +1695,9 @@ increment_stack (HOST_WIDE_INT amount) { inc = GEN_INT (amount); if (TARGET_LARGE) - emit_insn (gen_addpsi3 (sp, sp, inc)); + F (emit_insn (gen_addpsi3 (sp, sp, inc))); else - emit_insn (gen_addhi3 (sp, sp, inc)); + F (emit_insn (gen_addhi3 (sp, sp, inc))); } } @@ -2408,6 +2408,8 @@ msp430_expand_prologue (void) for (i = 15; i >= 4; i--) if (cfun->machine->need_to_save[i]) { + /* We need to save COUNT sequential registers starting from regnum + I. */ int seq, count; rtx note; @@ -2422,6 +2424,7 @@ msp430_expand_prologue (void) p = F (emit_insn (gen_pushm (gen_rtx_REG (Pmode, i), GEN_INT (count)))); + /* Document the stack decrement as a result of PUSHM. */ note = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (count + 1)); XVECEXP (note, 0, 0) @@ -2470,8 +2473,10 @@ msp430_expand_prologue (void) void msp430_expand_epilogue (int is_eh) { - int i; + int i, j; int fs; + rtx sp = stack_pointer_rtx; + rtx p; int helper_n = 0; if (is_naked_func ()) @@ -2540,19 +2545,27 @@ msp430_expand_epilogue (int is_eh) for (i = 4; i <= 15; i++) if (cfun->machine->need_to_save[i]) { - int seq, count; + /* We need to restore COUNT sequential registers starting from regnum + I. */ + int seq; + int count = 1; + int helper_used = 0; + rtx note, addr; - for (seq = i + 1; seq <= 15 && cfun->machine->need_to_save[seq]; seq ++) - ; - count = seq - i; + if (msp430x) + { + for (seq = i + 1; seq <= 15 && cfun->machine->need_to_save[seq]; + seq++) + ; + count = seq - i; + } if (msp430x) { /* Note: With TARGET_LARGE we still use POPM as POPX.A is two bytes bigger. */ - emit_insn (gen_popm (stack_pointer_rtx, GEN_INT (seq - 1), - GEN_INT (count))); - i += count - 1; + p = F (emit_insn (gen_popm (stack_pointer_rtx, GEN_INT (seq - 1), + GEN_INT (count)))); } else if (i == 11 - helper_n && ! msp430_is_interrupt_func () @@ -2564,11 +2577,44 @@ msp430_expand_epilogue (int is_eh) && helper_n > 1 && !is_eh) { - emit_jump_insn (gen_epilogue_helper (GEN_INT (helper_n))); - return; + p = F (emit_jump_insn (gen_epilogue_helper (GEN_INT (helper_n)))); + count = helper_n; + helper_used = 1; } else - emit_insn (gen_pop (gen_rtx_REG (Pmode, i))); + p = F (emit_insn (gen_pop (gen_rtx_REG (Pmode, i)))); + + /* Document the stack increment as a result of POPM. */ + note = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (count + 1)); + + addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx, + GEN_INT (count * (TARGET_LARGE ? 4 : 2))); + + XVECEXP (note, 0, 0) = F (gen_rtx_SET (stack_pointer_rtx, addr)); + + + /* *sp++ = R[i+j] */ + /* sp R4 + ... + sp+N R10. */ + for (j = 0; j < count; j++) + { + int ofs = j * (TARGET_LARGE ? 4 : 2); + + if (ofs) + addr = gen_rtx_PLUS (Pmode, sp, GEN_INT (ofs)); + else + addr = stack_pointer_rtx; + + XVECEXP (note, 0, j + 1) + = F (gen_rtx_SET (gen_rtx_MEM (Pmode, addr), + gen_rtx_REG (Pmode, i + j))); + } + add_reg_note (p, REG_FRAME_RELATED_EXPR, note); + i += count - 1; + + if (helper_used) + return; } if (is_eh) |