https://gcc.gnu.org/g:dee08b5feed336fe31e520115f6dcd18f84d24c8
commit r17-1558-gdee08b5feed336fe31e520115f6dcd18f84d24c8 Author: Monk Chiang <[email protected]> Date: Wed Jan 21 11:29:13 2026 +0800 RISC-V: Ensure Zicfilp lpad 4-byte alignment Add LABEL_ALIGN to align non-local goto target labels, removing the explicit gen_lpad_align () call. Extend gpr_save to emit the full CFI guard (.p2align 2, .option push/norelax/norvc, call, .option pop, lpad 0) when Zicfilp is active. Add lpad_align before the thunk entry lpad. gcc/ChangeLog: * config/riscv/riscv-zicfilp.cc (rest_of_insert_landing_pad): Remove gen_lpad_align before non-local goto labels; LABEL_ALIGN now handles their alignment. Simplify gpr_save handling: the pattern now outputs the full CFI sequence itself. * config/riscv/riscv.cc (riscv_output_mi_thunk): Add gen_lpad_align before entry lpad. * config/riscv/riscv.h (LABEL_ALIGN): New macro; ensures 4-byte alignment for Zicfilp non-local goto target labels. * config/riscv/riscv.md (gpr_save): When is_zicfilp_p, output .p2align 2, .option push/norelax/norvc, call, .option pop, lpad 0. gcc/testsuite/ChangeLog: * g++.target/riscv/zicfilp-thunk.C: New test. * gcc.target/riscv/zicfilp-func-entry.c: New test. * gcc.target/riscv/zicfilp-gpr-save.c: New test. * gcc.target/riscv/zicfilp-nonlocal-goto.c: New test. Diff: --- gcc/config/riscv/riscv-zicfilp.cc | 6 ++-- gcc/config/riscv/riscv.cc | 5 ++- gcc/config/riscv/riscv.h | 7 +++++ gcc/config/riscv/riscv.md | 19 ++++++++++-- gcc/testsuite/g++.target/riscv/zicfilp-thunk.C | 36 ++++++++++++++++++++++ .../gcc.target/riscv/zicfilp-func-entry.c | 15 +++++++++ gcc/testsuite/gcc.target/riscv/zicfilp-gpr-save.c | 27 ++++++++++++++++ .../gcc.target/riscv/zicfilp-nonlocal-goto.c | 31 +++++++++++++++++++ 8 files changed, 140 insertions(+), 6 deletions(-) diff --git a/gcc/config/riscv/riscv-zicfilp.cc b/gcc/config/riscv/riscv-zicfilp.cc index 04d9bd923392..6facdd702c39 100644 --- a/gcc/config/riscv/riscv-zicfilp.cc +++ b/gcc/config/riscv/riscv-zicfilp.cc @@ -107,16 +107,16 @@ rest_of_insert_landing_pad (void) && (LABEL_PRESERVE_P (insn) || bb->flags & BB_NON_LOCAL_GOTO_TARGET)) { - emit_insn_before (gen_lpad_align (), insn); emit_insn_after (gen_lpad (const0_rtx), insn); continue; } + /* gpr_save outputs the full CFI sequence when Zicfilp is active + Reset t2 to 0 so the hardware lpad check passes on return from + __riscv_save_N. */ if (INSN_P (insn) && INSN_CODE (insn) == CODE_FOR_gpr_save) { emit_move_insn (RISCV_CALL_ADDRESS_LPAD (Pmode), const0_rtx); - emit_insn_before (gen_lpad_align (), insn); - emit_insn_after (gen_lpad (const0_rtx), insn); continue; } diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index b1bdbf1a9ccb..3be5606ba015 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -11834,7 +11834,10 @@ riscv_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, emit_note (NOTE_INSN_PROLOGUE_END); if (is_zicfilp_p ()) - emit_insn (gen_lpad (const0_rtx)); + { + emit_insn (gen_lpad_align ()); + emit_insn (gen_lpad (const0_rtx)); + } /* Determine if we can use a sibcall to call FUNCTION directly. */ fnaddr = gen_rtx_MEM (FUNCTION_MODE, XEXP (DECL_RTL (function), 0)); diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h index cb821ae8b3a6..d72c06ec37f1 100644 --- a/gcc/config/riscv/riscv.h +++ b/gcc/config/riscv/riscv.h @@ -1105,6 +1105,13 @@ extern enum riscv_cc get_riscv_cc (const rtx use); fprintf (STREAM, "\t.word\t%sL%d-%sL%d\n", \ LOCAL_LABEL_PREFIX, VALUE, LOCAL_LABEL_PREFIX, REL) +/* For Zicfilp, labels that may be indirect jump targets need 4-byte + alignment so that the lpad instruction after them is properly aligned. */ +#define LABEL_ALIGN(LABEL) \ + (TARGET_ZICFILP && LABEL_PRESERVE_P (LABEL) \ + ? ((align_labels.levels[0].log > 2) ? align_labels : align_flags (2)) \ + : align_labels) + /* This is how to output an assembler line that says to advance the location counter to a multiple of 2**LOG bytes. */ diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 5231610b0540..88defdd43f0e 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -4347,8 +4347,23 @@ [(unspec_volatile [(match_operand 0 "const_int_operand")] UNSPECV_GPR_SAVE)])] "" - "call\tt0,__riscv_save_%0" - [(set_attr "type" "call")]) + { + if (is_zicfilp_p ()) + { + output_asm_insn (".p2align\t2", operands); + output_asm_insn (".option push", operands); + output_asm_insn (".option norelax", operands); + output_asm_insn (".option norvc", operands); + output_asm_insn ("call\tt0,__riscv_save_%0", operands); + output_asm_insn (".option pop", operands); + return "lpad\t0"; + } + return "call\tt0,__riscv_save_%0"; + } + [(set_attr "type" "call") + (set (attr "length") (if_then_else (match_test "is_zicfilp_p ()") + (const_string "12") + (const_string "8")))]) (define_insn "gpr_restore" [(unspec_volatile [(match_operand 0 "const_int_operand")] UNSPECV_GPR_RESTORE)] diff --git a/gcc/testsuite/g++.target/riscv/zicfilp-thunk.C b/gcc/testsuite/g++.target/riscv/zicfilp-thunk.C new file mode 100644 index 000000000000..68d67dbc4968 --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/zicfilp-thunk.C @@ -0,0 +1,36 @@ +/* Test RISC-V Zicfilp C++ thunk LPAD. */ +/* { dg-do compile { target { riscv64*-*-* } } } */ +/* { dg-options "-O2 -march=rv64gc_zicfilp -mabi=lp64d -fcf-protection=none -fcf-protection=branch" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-g" "-flto" } } */ +/* { dg-final { check-function-bodies "**" "" {\.align|lpad} } } */ + +class Base1 { +public: + virtual int method1 (int x) { return x + 1; } + int data1; +}; + +class Base2 { +public: + virtual int method2 (int x) { return x + 2; } + int data2; +}; + +class Derived : public Base1, public Base2 { +public: + virtual int method2 (int x) override { return x + 10; } +}; + +Derived global_derived; + +int call_method2 (Base2 *p) +{ + return p->method2 (42); +} + +/* +** _ZThn16_N7Derived7method2Ei: +** \.align 2 +** lpad \d+ +** ... +*/ diff --git a/gcc/testsuite/gcc.target/riscv/zicfilp-func-entry.c b/gcc/testsuite/gcc.target/riscv/zicfilp-func-entry.c new file mode 100644 index 000000000000..667acd829235 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zicfilp-func-entry.c @@ -0,0 +1,15 @@ +/* Test RISC-V Zicfilp function entry LPAD. */ +/* { dg-do compile { target { riscv64*-*-* } } } */ +/* { dg-options "-O2 -march=rv64gc_zicfilp -mabi=lp64d -fcf-protection=none -fcf-protection=branch" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-g" "-flto" } } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +/* +** public_function: +** lpad \d+ +** ... +*/ +int public_function (int a, int b) +{ + return a + b; +} diff --git a/gcc/testsuite/gcc.target/riscv/zicfilp-gpr-save.c b/gcc/testsuite/gcc.target/riscv/zicfilp-gpr-save.c new file mode 100644 index 000000000000..1d9b6446de44 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zicfilp-gpr-save.c @@ -0,0 +1,27 @@ +/* Test RISC-V Zicfilp gpr_save LPAD alignment with .option norelax. */ +/* { dg-do compile { target { riscv64*-*-* } } } */ +/* { dg-options "-O2 -msave-restore -fomit-frame-pointer -march=rv64gc_zicfilp -mabi=lp64d -fcf-protection=none -fcf-protection=branch" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-g" "-flto" } } */ +/* { dg-final { check-function-bodies "**" "" {\.p2align|\.option|call|lpad} } } */ + +extern void bar (void); + +/* +** foo: +** ... +** .p2align 2 +** .option push +** .option norelax +** .option norvc +** call t0,__riscv_save_[0-9]+ +** .option pop +** lpad \d+ +** ... +*/ +void foo (void) +{ + register long s0 asm ("s0"); + asm volatile ("li s0, 0x87654321" : "=r"(s0)); + bar (); + asm volatile ("" : : "r"(s0)); +} diff --git a/gcc/testsuite/gcc.target/riscv/zicfilp-nonlocal-goto.c b/gcc/testsuite/gcc.target/riscv/zicfilp-nonlocal-goto.c new file mode 100644 index 000000000000..1edd30f50273 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zicfilp-nonlocal-goto.c @@ -0,0 +1,31 @@ +/* Test RISC-V Zicfilp non-local goto LPAD with proper alignment. */ +/* { dg-do compile { target { riscv64*-*-* } } } */ +/* { dg-options "-march=rv64gc_zicfilp -mabi=lp64d -fcf-protection=none -fcf-protection=branch" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-O2" "-O3" "-Os" "-Oz" "-Og" "-g" "-flto" } } */ +/* { dg-final { check-function-bodies "**" "" {\.align|\.L[0-9]+:} } } */ + +extern void do_something (void); + +/* +** outer_function: +** lpad \d+ +** ... +** \.align 2 +** \.L[0-9]+: +** lpad \d+ +** ... +*/ +void outer_function (void *label_addr) +{ + __label__ target_label; + + if (label_addr) + goto *label_addr; + + do_something (); + +target_label: + do_something (); + + outer_function (&&target_label); +}
