[compiler-rt] [llvm] [RISC-V][Zicfiss] Move shadow stack ops to save/restore builtins (PR #222850)
Nemanja Ivanovic via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 10 23:13:49 PDT 2026
https://github.com/nemanjai created https://github.com/llvm/llvm-project/pull/222850
There is currently an incompatibility between save-restore and HW shadow stack protection. The callee-saved registers are saved/restored in the save/restore builtins, but the sspush/sspop are placed into the prologue/epilogue. This is less than ideal from a code size perspective since it emits the instructions in every prologue/epilogue. But even more importantly, it also means that the code is incorrect on any non-leaf function since the link register is restored after the sspopchk - which of coruse means that the sspopchk will fail.
This patch moves the instructions to where the registers are saved/restored. More specifically, the sspush is added to the places where the link register is saved and the sspopchk is added where the restore builtin returns.
>From d290824f76bef53757b4e4e1be07b44467d6787e Mon Sep 17 00:00:00 2001
From: Nemanja Ivanovic <nemanja.i.llvm at gmail.com>
Date: Fri, 11 Sep 2026 08:06:58 +0200
Subject: [PATCH] [RISC-V][Zicfiss] Move shadow stack ops to save/restore
builtins
There is currently an incompatibility between save-restore
and HW shadow stack protection. The callee-saved registers
are saved/restored in the save/restore builtins, but the
sspush/sspop are placed into the prologue/epilogue. This is
less than ideal from a code size perspective since it emits
the instructions in every prologue/epilogue. But even more
importantly, it also means that the code is incorrect on
any non-leaf function since the link register is restored
after the sspopchk - which of coruse means that the sspopchk
will fail.
This patch moves the instructions to where the registers are
saved/restored. More specifically, the sspush is added to
the places where the link register is saved and the sspopchk
is added where the restore builtin returns.
---
compiler-rt/lib/builtins/riscv/restore.S | 12 +
compiler-rt/lib/builtins/riscv/save.S | 30 ++
llvm/lib/Target/RISCV/RISCVFrameLowering.cpp | 21 +-
llvm/test/CodeGen/RISCV/shadowcallstack.ll | 288 +++++++++++++++++++
4 files changed, 345 insertions(+), 6 deletions(-)
diff --git a/compiler-rt/lib/builtins/riscv/restore.S b/compiler-rt/lib/builtins/riscv/restore.S
index 7816f74ed497e..de3c496ffca49 100644
--- a/compiler-rt/lib/builtins/riscv/restore.S
+++ b/compiler-rt/lib/builtins/riscv/restore.S
@@ -89,6 +89,9 @@ __riscv_restore_0:
lw s0, 8(sp)
lw ra, 12(sp)
addi sp, sp, 16
+#if defined(__riscv_shadow_stack)
+ sspopchk ra
+#endif
ret
#else
@@ -112,6 +115,9 @@ __riscv_restore_1:
__riscv_restore_0:
lw ra, 0(sp)
addi sp, sp, 4
+#if defined(__riscv_shadow_stack)
+ sspopchk ra
+#endif
ret
#endif
@@ -191,6 +197,9 @@ __riscv_restore_0:
ld s0, 0(sp)
ld ra, 8(sp)
addi sp, sp, 16
+#if defined(__riscv_shadow_stack)
+ sspopchk ra
+#endif
ret
#else
@@ -214,6 +223,9 @@ __riscv_restore_1:
__riscv_restore_0:
ld ra, 0(sp)
addi sp, sp, 8
+#if defined(__riscv_shadow_stack)
+ sspopchk ra
+#endif
ret
#endif
diff --git a/compiler-rt/lib/builtins/riscv/save.S b/compiler-rt/lib/builtins/riscv/save.S
index 6b50bce022524..0e14a1585e194 100644
--- a/compiler-rt/lib/builtins/riscv/save.S
+++ b/compiler-rt/lib/builtins/riscv/save.S
@@ -72,6 +72,9 @@ __riscv_save_4:
sw s1, 52(sp)
sw s0, 56(sp)
sw ra, 60(sp)
+#if defined(__riscv_shadow_stack)
+ sspush ra
+#endif
add sp, sp, t1
jr t0
@@ -92,6 +95,9 @@ __riscv_save_0:
sw s1, 4(sp)
sw s0, 8(sp)
sw ra, 12(sp)
+#if defined(__riscv_shadow_stack)
+ sspush ra
+#endif
jr t0
#else
@@ -103,6 +109,9 @@ __riscv_save_2:
sw s1, 0(sp)
sw s0, 4(sp)
sw ra, 8(sp)
+#if defined(__riscv_shadow_stack)
+ sspush ra
+#endif
jr t0
.globl __riscv_save_1
@@ -111,6 +120,9 @@ __riscv_save_1:
addi sp, sp, -8
sw s0, 0(sp)
sw ra, 4(sp)
+#if defined(__riscv_shadow_stack)
+ sspush ra
+#endif
jr t0
.globl __riscv_save_0
@@ -118,6 +130,9 @@ __riscv_save_1:
__riscv_save_0:
addi sp, sp, -4
sw ra, 0(sp)
+#if defined(__riscv_shadow_stack)
+ sspush ra
+#endif
jr t0
#endif
@@ -199,6 +214,9 @@ __riscv_save_2:
sd s1, 88(sp)
sd s0, 96(sp)
sd ra, 104(sp)
+#if defined(__riscv_shadow_stack)
+ sspush ra
+#endif
add sp, sp, t1
jr t0
@@ -211,6 +229,9 @@ __riscv_save_0:
addi sp, sp, -16
sd s0, 0(sp)
sd ra, 8(sp)
+#if defined(__riscv_shadow_stack)
+ sspush ra
+#endif
jr t0
#else
@@ -222,6 +243,9 @@ __riscv_save_2:
sw s1, 0(sp)
sw s0, 8(sp)
sw ra, 16(sp)
+#if defined(__riscv_shadow_stack)
+ sspush ra
+#endif
jr t0
.globl __riscv_save_1
@@ -230,6 +254,9 @@ __riscv_save_1:
addi sp, sp, -16
sw s0, 0(sp)
sw ra, 8(sp)
+#if defined(__riscv_shadow_stack)
+ sspush ra
+#endif
jr t0
.globl __riscv_save_0
@@ -237,6 +264,9 @@ __riscv_save_1:
__riscv_save_0:
addi sp, sp, -8
sw ra, 0(sp)
+#if defined(__riscv_shadow_stack)
+ sspush ra
+#endif
jr t0
#endif
diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index b50a18b539555..86d137a5b875d 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -1005,8 +1005,14 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
// SiFive CLIC needs to swap `sp` into `sf.mscratchcsw`
emitSiFiveCLICStackSwap(MF, MBB, MBBI, DL, MachineInstr::FrameSetup);
- // Emit prologue for shadow call stack.
- emitSCSPrologue(MF, MBB, MBBI, DL);
+ bool HasHWShadowStack = MF.getFunction().hasFnAttribute("hw-shadow-stack") &&
+ STI.hasStdExtZimop();
+ const auto &CSI = MFI.getCalleeSavedInfo();
+
+ // Emit prologue for shadow call stack except with save-restore (in which case
+ // that is deferred to the save-restore library routines).
+ if (!HasHWShadowStack || getLibCallID(MF, CSI) == -1)
+ emitSCSPrologue(MF, MBB, MBBI, DL);
// We keep track of the first instruction because it might be a
// `(QC.)CM.PUSH(FP)`, and we may need to adjust the immediate rather than
@@ -1020,8 +1026,6 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
// Determine the correct frame layout
determineFrameLayout(MF);
- const auto &CSI = MFI.getCalleeSavedInfo();
-
// Skip to before the spills of scalar callee-saved registers
// FIXME: assumes exactly one instruction is used to restore each
// callee-saved register.
@@ -1415,8 +1419,13 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
deallocateStack(MF, MBB, MBBI, DL, StackSize,
RVFI->getLibCallStackSize());
- // Emit epilogue for shadow call stack.
- emitSCSEpilogue(MF, MBB, MBBI, DL);
+ bool HasHWShadowStack =
+ MF.getFunction().hasFnAttribute("hw-shadow-stack") &&
+ STI.hasStdExtZimop();
+ // Emit epilogue for SW shadow call stack. For HW shadow stack, it is up to
+ // the library routines to perform these.
+ if (!HasHWShadowStack)
+ emitSCSEpilogue(MF, MBB, MBBI, DL);
return;
}
diff --git a/llvm/test/CodeGen/RISCV/shadowcallstack.ll b/llvm/test/CodeGen/RISCV/shadowcallstack.ll
index 24fa8037f3502..c4b3e326e62e9 100644
--- a/llvm/test/CodeGen/RISCV/shadowcallstack.ll
+++ b/llvm/test/CodeGen/RISCV/shadowcallstack.ll
@@ -13,8 +13,12 @@
; RUN: -verify-machineinstrs | FileCheck %s --check-prefixes=RV64-ZICFISS,RV64-NOZCMOP
; RUN: llc -mtriple=riscv32 -mattr=+zimop,+zcmop < %s -M no-aliases \
; RUN: -verify-machineinstrs | FileCheck %s --check-prefixes=RV32-ZICFISS,RV32-ZCMOP
+; RUN: llc -mtriple=riscv32 -mattr=+zimop,+zcmop,+save-restore < %s -M no-aliases \
+; RUN: -verify-machineinstrs | FileCheck %s --check-prefixes=RV32-SR
; RUN: llc -mtriple=riscv64 -mattr=+zimop,+zcmop < %s -M no-aliases \
; RUN: -verify-machineinstrs | FileCheck %s --check-prefixes=RV64-ZICFISS,RV64-ZCMOP
+; RUN: llc -mtriple=riscv64 -mattr=+zimop,+zcmop,+save-restore < %s -M no-aliases \
+; RUN: -verify-machineinstrs | FileCheck %s --check-prefix=RV64-SR
define void @f1() shadowcallstack {
; RV32-LABEL: f1:
@@ -45,9 +49,17 @@ define void @f1() shadowcallstack {
; RV32-ZCMOP: # %bb.0:
; RV32-ZCMOP-NEXT: c.jr ra
;
+; RV32-SR-LABEL: f1:
+; RV32-SR: # %bb.0:
+; RV32-SR-NEXT: c.jr ra
+;
; RV64-ZCMOP-LABEL: f1:
; RV64-ZCMOP: # %bb.0:
; RV64-ZCMOP-NEXT: c.jr ra
+;
+; RV64-SR-LABEL: f1:
+; RV64-SR: # %bb.0:
+; RV64-SR-NEXT: c.jr ra
ret void
}
@@ -77,6 +89,14 @@ define void @f2() shadowcallstack {
; RV64-ZICFISS-LABEL: f2:
; RV64-ZICFISS: # %bb.0:
; RV64-ZICFISS-NEXT: tail foo
+;
+; RV32-SR-LABEL: f2:
+; RV32-SR: # %bb.0:
+; RV32-SR-NEXT: tail foo
+;
+; RV64-SR-LABEL: f2:
+; RV64-SR: # %bb.0:
+; RV64-SR-NEXT: tail foo
tail call void @foo()
ret void
}
@@ -209,6 +229,20 @@ define i32 @f3() shadowcallstack {
; RV32-ZCMOP-NEXT: .cfi_restore gp
; RV32-ZCMOP-NEXT: c.jr ra
;
+; RV32-SR-LABEL: f3:
+; RV32-SR: # %bb.0:
+; RV32-SR-NEXT: c.addi gp, 4
+; RV32-SR-NEXT: sw ra, -4(gp)
+; RV32-SR-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32-SR-NEXT: call t0, __riscv_save_0
+; RV32-SR-NEXT: .cfi_def_cfa_offset 16
+; RV32-SR-NEXT: .cfi_offset ra, -4
+; RV32-SR-NEXT: call bar
+; RV32-SR-NEXT: lw ra, -4(gp)
+; RV32-SR-NEXT: c.addi gp, -4
+; RV32-SR-NEXT: .cfi_restore gp
+; RV32-SR-NEXT: tail __riscv_restore_0
+;
; RV64-ZCMOP-LABEL: f3:
; RV64-ZCMOP: # %bb.0:
; RV64-ZCMOP-NEXT: c.addi gp, 8
@@ -227,6 +261,20 @@ define i32 @f3() shadowcallstack {
; RV64-ZCMOP-NEXT: c.addi gp, -8
; RV64-ZCMOP-NEXT: .cfi_restore gp
; RV64-ZCMOP-NEXT: c.jr ra
+;
+; RV64-SR-LABEL: f3:
+; RV64-SR: # %bb.0:
+; RV64-SR-NEXT: c.addi gp, 8
+; RV64-SR-NEXT: sd ra, -8(gp)
+; RV64-SR-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64-SR-NEXT: call t0, __riscv_save_0
+; RV64-SR-NEXT: .cfi_def_cfa_offset 16
+; RV64-SR-NEXT: .cfi_offset ra, -8
+; RV64-SR-NEXT: call bar
+; RV64-SR-NEXT: ld ra, -8(gp)
+; RV64-SR-NEXT: c.addi gp, -8
+; RV64-SR-NEXT: .cfi_restore gp
+; RV64-SR-NEXT: tail __riscv_restore_0
%res = call i32 @bar()
%res1 = add i32 %res, 1
ret i32 %res
@@ -487,6 +535,32 @@ define i32 @f4() shadowcallstack {
; RV32-ZCMOP-NEXT: .cfi_restore gp
; RV32-ZCMOP-NEXT: c.jr ra
;
+; RV32-SR-LABEL: f4:
+; RV32-SR: # %bb.0:
+; RV32-SR-NEXT: c.addi gp, 4
+; RV32-SR-NEXT: sw ra, -4(gp)
+; RV32-SR-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32-SR-NEXT: call t0, __riscv_save_3
+; RV32-SR-NEXT: .cfi_def_cfa_offset 16
+; RV32-SR-NEXT: .cfi_offset ra, -4
+; RV32-SR-NEXT: .cfi_offset s0, -8
+; RV32-SR-NEXT: .cfi_offset s1, -12
+; RV32-SR-NEXT: .cfi_offset s2, -16
+; RV32-SR-NEXT: call bar
+; RV32-SR-NEXT: c.mv s0, a0
+; RV32-SR-NEXT: call bar
+; RV32-SR-NEXT: c.mv s1, a0
+; RV32-SR-NEXT: call bar
+; RV32-SR-NEXT: c.mv s2, a0
+; RV32-SR-NEXT: call bar
+; RV32-SR-NEXT: c.add s0, s1
+; RV32-SR-NEXT: c.add a0, s2
+; RV32-SR-NEXT: c.add a0, s0
+; RV32-SR-NEXT: lw ra, -4(gp)
+; RV32-SR-NEXT: c.addi gp, -4
+; RV32-SR-NEXT: .cfi_restore gp
+; RV32-SR-NEXT: tail __riscv_restore_3
+;
; RV64-ZCMOP-LABEL: f4:
; RV64-ZCMOP: # %bb.0:
; RV64-ZCMOP-NEXT: c.addi gp, 8
@@ -526,6 +600,32 @@ define i32 @f4() shadowcallstack {
; RV64-ZCMOP-NEXT: c.addi gp, -8
; RV64-ZCMOP-NEXT: .cfi_restore gp
; RV64-ZCMOP-NEXT: c.jr ra
+;
+; RV64-SR-LABEL: f4:
+; RV64-SR: # %bb.0:
+; RV64-SR-NEXT: c.addi gp, 8
+; RV64-SR-NEXT: sd ra, -8(gp)
+; RV64-SR-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64-SR-NEXT: call t0, __riscv_save_3
+; RV64-SR-NEXT: .cfi_def_cfa_offset 32
+; RV64-SR-NEXT: .cfi_offset ra, -8
+; RV64-SR-NEXT: .cfi_offset s0, -16
+; RV64-SR-NEXT: .cfi_offset s1, -24
+; RV64-SR-NEXT: .cfi_offset s2, -32
+; RV64-SR-NEXT: call bar
+; RV64-SR-NEXT: c.mv s0, a0
+; RV64-SR-NEXT: call bar
+; RV64-SR-NEXT: c.mv s1, a0
+; RV64-SR-NEXT: call bar
+; RV64-SR-NEXT: c.mv s2, a0
+; RV64-SR-NEXT: call bar
+; RV64-SR-NEXT: c.add s0, s1
+; RV64-SR-NEXT: c.add a0, s2
+; RV64-SR-NEXT: c.addw a0, s0
+; RV64-SR-NEXT: ld ra, -8(gp)
+; RV64-SR-NEXT: c.addi gp, -8
+; RV64-SR-NEXT: .cfi_restore gp
+; RV64-SR-NEXT: tail __riscv_restore_3
%res1 = call i32 @bar()
%res2 = call i32 @bar()
%res3 = call i32 @bar()
@@ -624,6 +724,16 @@ define i32 @f5() shadowcallstack nounwind {
; RV32-ZCMOP-NEXT: c.addi gp, -4
; RV32-ZCMOP-NEXT: c.jr ra
;
+; RV32-SR-LABEL: f5:
+; RV32-SR: # %bb.0:
+; RV32-SR-NEXT: c.addi gp, 4
+; RV32-SR-NEXT: sw ra, -4(gp)
+; RV32-SR-NEXT: call t0, __riscv_save_0
+; RV32-SR-NEXT: call bar
+; RV32-SR-NEXT: lw ra, -4(gp)
+; RV32-SR-NEXT: c.addi gp, -4
+; RV32-SR-NEXT: tail __riscv_restore_0
+;
; RV64-ZCMOP-LABEL: f5:
; RV64-ZCMOP: # %bb.0:
; RV64-ZCMOP-NEXT: c.addi gp, 8
@@ -636,6 +746,16 @@ define i32 @f5() shadowcallstack nounwind {
; RV64-ZCMOP-NEXT: ld ra, -8(gp)
; RV64-ZCMOP-NEXT: c.addi gp, -8
; RV64-ZCMOP-NEXT: c.jr ra
+;
+; RV64-SR-LABEL: f5:
+; RV64-SR: # %bb.0:
+; RV64-SR-NEXT: c.addi gp, 8
+; RV64-SR-NEXT: sd ra, -8(gp)
+; RV64-SR-NEXT: call t0, __riscv_save_0
+; RV64-SR-NEXT: call bar
+; RV64-SR-NEXT: ld ra, -8(gp)
+; RV64-SR-NEXT: c.addi gp, -8
+; RV64-SR-NEXT: tail __riscv_restore_0
%res = call i32 @bar()
%res1 = add i32 %res, 1
ret i32 %res
@@ -670,9 +790,17 @@ define void @f1_hw() "hw-shadow-stack" {
; RV32-ZCMOP: # %bb.0:
; RV32-ZCMOP-NEXT: c.jr ra
;
+; RV32-SR-LABEL: f1_hw:
+; RV32-SR: # %bb.0:
+; RV32-SR-NEXT: c.jr ra
+;
; RV64-ZCMOP-LABEL: f1_hw:
; RV64-ZCMOP: # %bb.0:
; RV64-ZCMOP-NEXT: c.jr ra
+;
+; RV64-SR-LABEL: f1_hw:
+; RV64-SR: # %bb.0:
+; RV64-SR-NEXT: c.jr ra
ret void
}
@@ -700,6 +828,14 @@ define void @f2_hw() "hw-shadow-stack" {
; RV64-ZICFISS-LABEL: f2_hw:
; RV64-ZICFISS: # %bb.0:
; RV64-ZICFISS-NEXT: tail foo
+;
+; RV32-SR-LABEL: f2_hw:
+; RV32-SR: # %bb.0:
+; RV32-SR-NEXT: tail foo
+;
+; RV64-SR-LABEL: f2_hw:
+; RV64-SR: # %bb.0:
+; RV64-SR-NEXT: tail foo
tail call void @foo()
ret void
}
@@ -798,6 +934,14 @@ define i32 @f3_hw() "hw-shadow-stack" {
; RV32-ZCMOP-NEXT: sspopchk ra
; RV32-ZCMOP-NEXT: c.jr ra
;
+; RV32-SR-LABEL: f3_hw:
+; RV32-SR: # %bb.0:
+; RV32-SR-NEXT: call t0, __riscv_save_0
+; RV32-SR-NEXT: .cfi_def_cfa_offset 16
+; RV32-SR-NEXT: .cfi_offset ra, -4
+; RV32-SR-NEXT: call bar
+; RV32-SR-NEXT: tail __riscv_restore_0
+;
; RV64-ZCMOP-LABEL: f3_hw:
; RV64-ZCMOP: # %bb.0:
; RV64-ZCMOP-NEXT: c.sspush ra
@@ -812,6 +956,14 @@ define i32 @f3_hw() "hw-shadow-stack" {
; RV64-ZCMOP-NEXT: .cfi_def_cfa_offset 0
; RV64-ZCMOP-NEXT: sspopchk ra
; RV64-ZCMOP-NEXT: c.jr ra
+;
+; RV64-SR-LABEL: f3_hw:
+; RV64-SR: # %bb.0:
+; RV64-SR-NEXT: call t0, __riscv_save_0
+; RV64-SR-NEXT: .cfi_def_cfa_offset 16
+; RV64-SR-NEXT: .cfi_offset ra, -8
+; RV64-SR-NEXT: call bar
+; RV64-SR-NEXT: tail __riscv_restore_0
%res = call i32 @bar()
%res1 = add i32 %res, 1
ret i32 %res
@@ -1040,6 +1192,26 @@ define i32 @f4_hw() "hw-shadow-stack" {
; RV32-ZCMOP-NEXT: sspopchk ra
; RV32-ZCMOP-NEXT: c.jr ra
;
+; RV32-SR-LABEL: f4_hw:
+; RV32-SR: # %bb.0:
+; RV32-SR-NEXT: call t0, __riscv_save_3
+; RV32-SR-NEXT: .cfi_def_cfa_offset 16
+; RV32-SR-NEXT: .cfi_offset ra, -4
+; RV32-SR-NEXT: .cfi_offset s0, -8
+; RV32-SR-NEXT: .cfi_offset s1, -12
+; RV32-SR-NEXT: .cfi_offset s2, -16
+; RV32-SR-NEXT: call bar
+; RV32-SR-NEXT: c.mv s0, a0
+; RV32-SR-NEXT: call bar
+; RV32-SR-NEXT: c.mv s1, a0
+; RV32-SR-NEXT: call bar
+; RV32-SR-NEXT: c.mv s2, a0
+; RV32-SR-NEXT: call bar
+; RV32-SR-NEXT: c.add s0, s1
+; RV32-SR-NEXT: c.add a0, s2
+; RV32-SR-NEXT: c.add a0, s0
+; RV32-SR-NEXT: tail __riscv_restore_3
+;
; RV64-ZCMOP-LABEL: f4_hw:
; RV64-ZCMOP: # %bb.0:
; RV64-ZCMOP-NEXT: c.sspush ra
@@ -1075,6 +1247,26 @@ define i32 @f4_hw() "hw-shadow-stack" {
; RV64-ZCMOP-NEXT: .cfi_def_cfa_offset 0
; RV64-ZCMOP-NEXT: sspopchk ra
; RV64-ZCMOP-NEXT: c.jr ra
+;
+; RV64-SR-LABEL: f4_hw:
+; RV64-SR: # %bb.0:
+; RV64-SR-NEXT: call t0, __riscv_save_3
+; RV64-SR-NEXT: .cfi_def_cfa_offset 32
+; RV64-SR-NEXT: .cfi_offset ra, -8
+; RV64-SR-NEXT: .cfi_offset s0, -16
+; RV64-SR-NEXT: .cfi_offset s1, -24
+; RV64-SR-NEXT: .cfi_offset s2, -32
+; RV64-SR-NEXT: call bar
+; RV64-SR-NEXT: c.mv s0, a0
+; RV64-SR-NEXT: call bar
+; RV64-SR-NEXT: c.mv s1, a0
+; RV64-SR-NEXT: call bar
+; RV64-SR-NEXT: c.mv s2, a0
+; RV64-SR-NEXT: call bar
+; RV64-SR-NEXT: c.add s0, s1
+; RV64-SR-NEXT: c.add a0, s2
+; RV64-SR-NEXT: c.addw a0, s0
+; RV64-SR-NEXT: tail __riscv_restore_3
%res1 = call i32 @bar()
%res2 = call i32 @bar()
%res3 = call i32 @bar()
@@ -1155,6 +1347,12 @@ define i32 @f5_hw() "hw-shadow-stack" nounwind {
; RV32-ZCMOP-NEXT: sspopchk ra
; RV32-ZCMOP-NEXT: c.jr ra
;
+; RV32-SR-LABEL: f5_hw:
+; RV32-SR: # %bb.0:
+; RV32-SR-NEXT: call t0, __riscv_save_0
+; RV32-SR-NEXT: call bar
+; RV32-SR-NEXT: tail __riscv_restore_0
+;
; RV64-ZCMOP-LABEL: f5_hw:
; RV64-ZCMOP: # %bb.0:
; RV64-ZCMOP-NEXT: c.sspush ra
@@ -1165,6 +1363,12 @@ define i32 @f5_hw() "hw-shadow-stack" nounwind {
; RV64-ZCMOP-NEXT: c.addi sp, 16
; RV64-ZCMOP-NEXT: sspopchk ra
; RV64-ZCMOP-NEXT: c.jr ra
+;
+; RV64-SR-LABEL: f5_hw:
+; RV64-SR: # %bb.0:
+; RV64-SR-NEXT: call t0, __riscv_save_0
+; RV64-SR-NEXT: call bar
+; RV64-SR-NEXT: tail __riscv_restore_0
%res = call i32 @bar()
%res1 = add i32 %res, 1
ret i32 %res
@@ -1199,9 +1403,17 @@ define void @f1_both() "hw-shadow-stack" shadowcallstack {
; RV32-ZCMOP: # %bb.0:
; RV32-ZCMOP-NEXT: c.jr ra
;
+; RV32-SR-LABEL: f1_both:
+; RV32-SR: # %bb.0:
+; RV32-SR-NEXT: c.jr ra
+;
; RV64-ZCMOP-LABEL: f1_both:
; RV64-ZCMOP: # %bb.0:
; RV64-ZCMOP-NEXT: c.jr ra
+;
+; RV64-SR-LABEL: f1_both:
+; RV64-SR: # %bb.0:
+; RV64-SR-NEXT: c.jr ra
ret void
}
@@ -1229,6 +1441,14 @@ define void @f2_both() "hw-shadow-stack" shadowcallstack {
; RV64-ZICFISS-LABEL: f2_both:
; RV64-ZICFISS: # %bb.0:
; RV64-ZICFISS-NEXT: tail foo
+;
+; RV32-SR-LABEL: f2_both:
+; RV32-SR: # %bb.0:
+; RV32-SR-NEXT: tail foo
+;
+; RV64-SR-LABEL: f2_both:
+; RV64-SR: # %bb.0:
+; RV64-SR-NEXT: tail foo
tail call void @foo()
ret void
}
@@ -1339,6 +1559,14 @@ define i32 @f3_both() "hw-shadow-stack" shadowcallstack {
; RV32-ZCMOP-NEXT: sspopchk ra
; RV32-ZCMOP-NEXT: c.jr ra
;
+; RV32-SR-LABEL: f3_both:
+; RV32-SR: # %bb.0:
+; RV32-SR-NEXT: call t0, __riscv_save_0
+; RV32-SR-NEXT: .cfi_def_cfa_offset 16
+; RV32-SR-NEXT: .cfi_offset ra, -4
+; RV32-SR-NEXT: call bar
+; RV32-SR-NEXT: tail __riscv_restore_0
+;
; RV64-ZCMOP-LABEL: f3_both:
; RV64-ZCMOP: # %bb.0:
; RV64-ZCMOP-NEXT: c.sspush ra
@@ -1353,6 +1581,14 @@ define i32 @f3_both() "hw-shadow-stack" shadowcallstack {
; RV64-ZCMOP-NEXT: .cfi_def_cfa_offset 0
; RV64-ZCMOP-NEXT: sspopchk ra
; RV64-ZCMOP-NEXT: c.jr ra
+;
+; RV64-SR-LABEL: f3_both:
+; RV64-SR: # %bb.0:
+; RV64-SR-NEXT: call t0, __riscv_save_0
+; RV64-SR-NEXT: .cfi_def_cfa_offset 16
+; RV64-SR-NEXT: .cfi_offset ra, -8
+; RV64-SR-NEXT: call bar
+; RV64-SR-NEXT: tail __riscv_restore_0
%res = call i32 @bar()
%res1 = add i32 %res, 1
ret i32 %res
@@ -1593,6 +1829,26 @@ define i32 @f4_both() "hw-shadow-stack" shadowcallstack {
; RV32-ZCMOP-NEXT: sspopchk ra
; RV32-ZCMOP-NEXT: c.jr ra
;
+; RV32-SR-LABEL: f4_both:
+; RV32-SR: # %bb.0:
+; RV32-SR-NEXT: call t0, __riscv_save_3
+; RV32-SR-NEXT: .cfi_def_cfa_offset 16
+; RV32-SR-NEXT: .cfi_offset ra, -4
+; RV32-SR-NEXT: .cfi_offset s0, -8
+; RV32-SR-NEXT: .cfi_offset s1, -12
+; RV32-SR-NEXT: .cfi_offset s2, -16
+; RV32-SR-NEXT: call bar
+; RV32-SR-NEXT: c.mv s0, a0
+; RV32-SR-NEXT: call bar
+; RV32-SR-NEXT: c.mv s1, a0
+; RV32-SR-NEXT: call bar
+; RV32-SR-NEXT: c.mv s2, a0
+; RV32-SR-NEXT: call bar
+; RV32-SR-NEXT: c.add s0, s1
+; RV32-SR-NEXT: c.add a0, s2
+; RV32-SR-NEXT: c.add a0, s0
+; RV32-SR-NEXT: tail __riscv_restore_3
+;
; RV64-ZCMOP-LABEL: f4_both:
; RV64-ZCMOP: # %bb.0:
; RV64-ZCMOP-NEXT: c.sspush ra
@@ -1628,6 +1884,26 @@ define i32 @f4_both() "hw-shadow-stack" shadowcallstack {
; RV64-ZCMOP-NEXT: .cfi_def_cfa_offset 0
; RV64-ZCMOP-NEXT: sspopchk ra
; RV64-ZCMOP-NEXT: c.jr ra
+;
+; RV64-SR-LABEL: f4_both:
+; RV64-SR: # %bb.0:
+; RV64-SR-NEXT: call t0, __riscv_save_3
+; RV64-SR-NEXT: .cfi_def_cfa_offset 32
+; RV64-SR-NEXT: .cfi_offset ra, -8
+; RV64-SR-NEXT: .cfi_offset s0, -16
+; RV64-SR-NEXT: .cfi_offset s1, -24
+; RV64-SR-NEXT: .cfi_offset s2, -32
+; RV64-SR-NEXT: call bar
+; RV64-SR-NEXT: c.mv s0, a0
+; RV64-SR-NEXT: call bar
+; RV64-SR-NEXT: c.mv s1, a0
+; RV64-SR-NEXT: call bar
+; RV64-SR-NEXT: c.mv s2, a0
+; RV64-SR-NEXT: call bar
+; RV64-SR-NEXT: c.add s0, s1
+; RV64-SR-NEXT: c.add a0, s2
+; RV64-SR-NEXT: c.addw a0, s0
+; RV64-SR-NEXT: tail __riscv_restore_3
%res1 = call i32 @bar()
%res2 = call i32 @bar()
%res3 = call i32 @bar()
@@ -1716,6 +1992,12 @@ define i32 @f5_both() "hw-shadow-stack" shadowcallstack nounwind {
; RV32-ZCMOP-NEXT: sspopchk ra
; RV32-ZCMOP-NEXT: c.jr ra
;
+; RV32-SR-LABEL: f5_both:
+; RV32-SR: # %bb.0:
+; RV32-SR-NEXT: call t0, __riscv_save_0
+; RV32-SR-NEXT: call bar
+; RV32-SR-NEXT: tail __riscv_restore_0
+;
; RV64-ZCMOP-LABEL: f5_both:
; RV64-ZCMOP: # %bb.0:
; RV64-ZCMOP-NEXT: c.sspush ra
@@ -1726,6 +2008,12 @@ define i32 @f5_both() "hw-shadow-stack" shadowcallstack nounwind {
; RV64-ZCMOP-NEXT: c.addi sp, 16
; RV64-ZCMOP-NEXT: sspopchk ra
; RV64-ZCMOP-NEXT: c.jr ra
+;
+; RV64-SR-LABEL: f5_both:
+; RV64-SR: # %bb.0:
+; RV64-SR-NEXT: call t0, __riscv_save_0
+; RV64-SR-NEXT: call bar
+; RV64-SR-NEXT: tail __riscv_restore_0
%res = call i32 @bar()
%res1 = add i32 %res, 1
ret i32 %res
More information about the llvm-commits
mailing list