Fixes incorrect SP-addresses used in CFA notes for the stack probes
unrelative to the frame's top. It applied to the RISC-V targets code
generation when the stack-clash protection is enabled.

gcc/ChangeLog:

        * config/riscv/riscv.cc (riscv_allocate_and_probe_stack_space):
          Fix SP-addresses in REG_CFA_DEF_CFA notes for stack-clash case.

gcc/testsuite/ChangeLog:

        * gcc.target/riscv/pr120714.c: New test.

Signed-off-by: Alexey Merzlyakov <alexey.merzlya...@samsung.com>
---
 gcc/config/riscv/riscv.cc                 | 13 ++++++--
 gcc/testsuite/gcc.target/riscv/pr120714.c | 40 +++++++++++++++++++++++
 2 files changed, 51 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/pr120714.c

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 3c1bb74675a..4ac5ad998fb 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -8976,12 +8976,20 @@ riscv_allocate_and_probe_stack_space (rtx temp1, 
HOST_WIDE_INT size)
       temp2 = riscv_force_temporary (temp2, gen_int_mode (rounded_size, 
Pmode));
       insn = emit_insn (gen_sub3_insn (temp2, stack_pointer_rtx, temp2));
 
+      /* The size does not represent actual stack pointer address shift
+        from the top of the frame, as it might be lowered before.
+        To consider the correct SP addresses for the CFA notes, it is needed
+        to correct them with the initial offset value.  */
+      HOST_WIDE_INT initial_cfa_offset
+       = cfun->machine->frame.total_size.to_constant () - size;
+
       if (!frame_pointer_needed)
        {
          /* We want the CFA independent of the stack pointer for the
             duration of the loop.  */
          add_reg_note (insn, REG_CFA_DEF_CFA,
-                       plus_constant (Pmode, temp1, rounded_size));
+                       plus_constant (Pmode, temp1,
+                                      initial_cfa_offset + rounded_size));
          RTX_FRAME_RELATED_P (insn) = 1;
        }
 
@@ -8994,7 +9002,8 @@ riscv_allocate_and_probe_stack_space (rtx temp1, 
HOST_WIDE_INT size)
        {
          insn = get_last_insn ();
          add_reg_note (insn, REG_CFA_DEF_CFA,
-                       plus_constant (Pmode, stack_pointer_rtx, rounded_size));
+                       plus_constant (Pmode, stack_pointer_rtx,
+                                      initial_cfa_offset + rounded_size));
          RTX_FRAME_RELATED_P (insn) = 1;
        }
 
diff --git a/gcc/testsuite/gcc.target/riscv/pr120714.c 
b/gcc/testsuite/gcc.target/riscv/pr120714.c
new file mode 100644
index 00000000000..dd71a3e11d3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr120714.c
@@ -0,0 +1,40 @@
+/* Test checking that the backtrace on large frame size with additional
+   SP shift in the prologue won't broken when compiled with the
+   -fstack-clash-protection option.  */
+/* { dg-do run { target { *-*-linux* } } } */
+/* -O0 does not have enough optimizations.
+   -O2/-O3 does inline and reduces number of addresses in the backtrace.  */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O2" "-O3" } } */
+/* { dg-options "-g -fstack-clash-protection" } */
+
+#include <execinfo.h>
+
+#define MAX 4000
+
+void goo ()
+{
+  int addresses;
+  void *buffer[10];
+
+  addresses = backtrace (buffer, 10);
+  if (addresses != 6)
+    __builtin_abort ();
+}
+
+int foo (int a)
+{
+  long long A[MAX];
+  for (int i = 0; i < MAX; i++)
+    A[i] = i;
+
+  goo ();
+
+  return A[a % MAX];
+}
+
+int main ()
+{
+  if (foo (20) != 20)
+    __builtin_abort ();
+  return 0;
+}
-- 
2.34.1



Reply via email to