https://gcc.gnu.org/g:4dcd3c7749734133f7f59509b1a118f3a13de4ee

commit r15-7681-g4dcd3c7749734133f7f59509b1a118f3a13de4ee
Author: Lino Hsing-Yu Peng <linop...@andestech.com>
Date:   Thu Feb 20 17:09:22 2025 +0800

    RISC-V: Fix .cfi_offset directive when push/pop in zcmp
    
    The incorrect cfi directive info breaks stack unwind in try/catch/cxa.
    
    Before patch:
      cm.push       {ra, s0-s2}, -16
      .cfi_offset 1, -12
      .cfi_offset 8, -8
      .cfi_offset 18, -4
    
    After patch:
      cm.push       {ra, s0-s2}, -16
      .cfi_offset 1, -16
      .cfi_offset 8, -12
      .cfi_offset 9, -8
      .cfi_offset 18, -4
    
    gcc/ChangeLog:
    
            * config/riscv/riscv.cc: Set multi push regs bits.
    
    gcc/testsuite/ChangeLog:
            * gcc.target/riscv/zcmp_push_gpr.c: New test.

Diff:
---
 gcc/config/riscv/riscv.cc                      | 13 +++++++++++--
 gcc/testsuite/gcc.target/riscv/zcmp_push_gpr.c | 12 ++++++++++++
 2 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 9bf7713139f6..89aa25d5da92 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -728,6 +728,12 @@ static const unsigned gpr_save_reg_order[] = {
   S10_REGNUM, S11_REGNUM
 };
 
+/* Order for the (ra, s0-sx) of zcmp_save.  */
+static const unsigned zcmp_save_reg_order[]
+  = {RETURN_ADDR_REGNUM, S0_REGNUM,  S1_REGNUM,         S2_REGNUM,     
S3_REGNUM,
+     S4_REGNUM,                 S5_REGNUM,  S6_REGNUM,  S7_REGNUM,     
S8_REGNUM,
+     S9_REGNUM,                 S10_REGNUM, S11_REGNUM, INVALID_REGNUM};
+
 /* A table describing all the processors GCC knows about.  */
 static const struct riscv_tune_info riscv_tune_info_table[] = {
 #define RISCV_TUNE(TUNE_NAME, PIPELINE_MODEL, TUNE_INFO)       \
@@ -8364,8 +8370,11 @@ riscv_adjust_multi_push_cfi_prologue (int saved_size)
   int offset;
   int saved_cnt = 0;
 
-  if (mask & S10_MASK)
-    mask |= S11_MASK;
+  unsigned int num_multi_push = riscv_multi_push_regs_count (mask);
+  for (unsigned int i = 0; i < num_multi_push; i++) {
+    gcc_assert(zcmp_save_reg_order[i] != INVALID_REGNUM);
+    mask |= 1 << (zcmp_save_reg_order[i] - GP_REG_FIRST);
+  }
 
   for (int regno = GP_REG_LAST; regno >= GP_REG_FIRST; regno--)
     if (BITSET_P (mask & MULTI_PUSH_GPR_MASK, regno - GP_REG_FIRST))
diff --git a/gcc/testsuite/gcc.target/riscv/zcmp_push_gpr.c 
b/gcc/testsuite/gcc.target/riscv/zcmp_push_gpr.c
new file mode 100644
index 000000000000..acebafa41abd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zcmp_push_gpr.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32imafd_zicsr_zifencei_zca_zcmp -mabi=ilp32d -Os -g" 
} */
+/* { dg-skip-if "" { *-*-* } {"-O0" "-O1" "-O2" "-Og" "-O3" "-Oz" "-flto"} } */
+
+int
+zcmp_push ()
+{
+  __asm__ __volatile__("" ::: "ra", "s0", "s2");
+  return 0;
+}
+
+/* { dg-final { scan-assembler ".cfi_offset 1, -16\n\t.cfi_offset 8, 
-12\n\t.cfi_offset 9, -8\n\t.cfi_offset 18, -4\n\t.cfi_def_cfa_offset 16" } } */

Reply via email to