diff options
author | Lino Hsing-Yu Peng <linopeng@andestech.com> | 2025-02-20 17:09:22 +0800 |
---|---|---|
committer | Kito Cheng <kito.cheng@sifive.com> | 2025-02-24 16:04:32 +0800 |
commit | 4dcd3c7749734133f7f59509b1a118f3a13de4ee (patch) | |
tree | c8faba7570b3cfbecf9bf27542202500b079abe4 /gcc | |
parent | 7cfb2c8839c4ccaaf7d66f446c4c0d040b710f18 (diff) | |
download | gcc-4dcd3c7749734133f7f59509b1a118f3a13de4ee.zip gcc-4dcd3c7749734133f7f59509b1a118f3a13de4ee.tar.gz gcc-4dcd3c7749734133f7f59509b1a118f3a13de4ee.tar.bz2 |
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.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/riscv/riscv.cc | 13 | ||||
-rw-r--r-- | 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 9bf7713..89aa25d 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 0000000..acebafa --- /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" } } */ |