From 7cca6e23b293bdf47280997df87a0cda70d2f91d Mon Sep 17 00:00:00 2001
From: Lino Hsing-Yu Peng <linopeng@andestech.com>
Date: Thu, 20 Feb 2025 17:09:22 +0800
Subject: [PATCH] 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.
---
 gcc/config/riscv/riscv.cc                      | 11 +++++++++++
 gcc/testsuite/gcc.target/riscv/zcmp_push_gpr.c | 12 ++++++++++++
 2 files changed, 23 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/riscv/zcmp_push_gpr.c

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 9bf7713139f..5badfc8396f 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)	\
@@ -7772,6 +7778,11 @@ riscv_compute_frame_info (void)
 	  unsigned num_multi_push = riscv_multi_push_regs_count (frame->mask);
 	  x_save_size = riscv_stack_align (num_multi_push * UNITS_PER_WORD);
 	  frame->multi_push_adj_base = riscv_16bytes_align (x_save_size);
+	  for (int i = 0; i < num_multi_push; i++)
+	    {
+	      gcc_assert (zcmp_save_reg_order[i] != INVALID_REGNUM);
+	      frame->mask |= 1 << (zcmp_save_reg_order[i] - 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 00000000000..acebafa41ab
--- /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" } } */
-- 
2.34.1

Reply via email to