diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp index 30131862c1145..9d09b1628c88c 100644 --- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp @@ -67,10 +67,14 @@ static const std::pair FixedCSRFIMap[] = { static void emitSCSPrologue(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL) { - if (!MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack)) + const auto &STI = MF.getSubtarget(); + bool HasHWShadowStack = MF.getFunction().hasFnAttribute("hw-shadow-stack") && + STI.hasStdExtZicfiss(); + bool HasSWShadowStack = + MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack); + if (!HasHWShadowStack && !HasSWShadowStack) return; - const auto &STI = MF.getSubtarget(); const llvm::RISCVRegisterInfo *TRI = STI.getRegisterInfo(); Register RAReg = TRI->getRARegister(); @@ -82,7 +86,7 @@ static void emitSCSPrologue(MachineFunction &MF, MachineBasicBlock &MBB, return; const RISCVInstrInfo *TII = STI.getInstrInfo(); - if (!STI.hasForcedSWShadowStack() && STI.hasStdExtZicfiss()) { + if (HasHWShadowStack) { BuildMI(MBB, MI, DL, TII->get(RISCV::SSPUSH)).addReg(RAReg); return; } @@ -129,10 +133,14 @@ static void emitSCSPrologue(MachineFunction &MF, MachineBasicBlock &MBB, static void emitSCSEpilogue(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL) { - if (!MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack)) + const auto &STI = MF.getSubtarget(); + bool HasHWShadowStack = MF.getFunction().hasFnAttribute("hw-shadow-stack") && + STI.hasStdExtZicfiss(); + bool HasSWShadowStack = + MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack); + if (!HasHWShadowStack && !HasSWShadowStack) return; - const auto &STI = MF.getSubtarget(); Register RAReg = STI.getRegisterInfo()->getRARegister(); // See emitSCSPrologue() above. @@ -142,7 +150,7 @@ static void emitSCSEpilogue(MachineFunction &MF, MachineBasicBlock &MBB, return; const RISCVInstrInfo *TII = STI.getInstrInfo(); - if (!STI.hasForcedSWShadowStack() && STI.hasStdExtZicfiss()) { + if (HasHWShadowStack) { BuildMI(MBB, MI, DL, TII->get(RISCV::SSPOPCHK)).addReg(RAReg); return; } diff --git a/llvm/test/CodeGen/RISCV/shadowcallstack.ll b/llvm/test/CodeGen/RISCV/shadowcallstack.ll index 0c62fb4050051..03acd9491fed8 100644 --- a/llvm/test/CodeGen/RISCV/shadowcallstack.ll +++ b/llvm/test/CodeGen/RISCV/shadowcallstack.ll @@ -7,10 +7,6 @@ ; RUN: -verify-machineinstrs | FileCheck %s --check-prefix=RV32-ZICFISS ; RUN: llc -mtriple=riscv64 -mattr=+experimental-zicfiss < %s \ ; RUN: -verify-machineinstrs | FileCheck %s --check-prefix=RV64-ZICFISS -; RUN: llc -mtriple=riscv32 -mattr=+experimental-zicfiss,forced-sw-shadow-stack \ -; RUN: -verify-machineinstrs < %s | FileCheck %s --check-prefix=RV32 -; RUN: llc -mtriple=riscv64 -mattr=+experimental-zicfiss,forced-sw-shadow-stack \ -; RUN: -verify-machineinstrs < %s | FileCheck %s --check-prefix=RV64 define void @f1() shadowcallstack { ; RV32-LABEL: f1: @@ -96,7 +92,9 @@ define i32 @f3() shadowcallstack { ; ; RV32-ZICFISS-LABEL: f3: ; RV32-ZICFISS: # %bb.0: -; RV32-ZICFISS-NEXT: sspush ra +; RV32-ZICFISS-NEXT: addi gp, gp, 4 +; RV32-ZICFISS-NEXT: sw ra, -4(gp) +; RV32-ZICFISS-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c # ; RV32-ZICFISS-NEXT: addi sp, sp, -16 ; RV32-ZICFISS-NEXT: .cfi_def_cfa_offset 16 ; RV32-ZICFISS-NEXT: sw ra, 12(sp) # 4-byte Folded Spill @@ -106,12 +104,16 @@ define i32 @f3() shadowcallstack { ; RV32-ZICFISS-NEXT: .cfi_restore ra ; RV32-ZICFISS-NEXT: addi sp, sp, 16 ; RV32-ZICFISS-NEXT: .cfi_def_cfa_offset 0 -; RV32-ZICFISS-NEXT: sspopchk ra +; RV32-ZICFISS-NEXT: lw ra, -4(gp) +; RV32-ZICFISS-NEXT: addi gp, gp, -4 +; RV32-ZICFISS-NEXT: .cfi_restore gp ; RV32-ZICFISS-NEXT: ret ; ; RV64-ZICFISS-LABEL: f3: ; RV64-ZICFISS: # %bb.0: -; RV64-ZICFISS-NEXT: sspush ra +; RV64-ZICFISS-NEXT: addi gp, gp, 8 +; RV64-ZICFISS-NEXT: sd ra, -8(gp) +; RV64-ZICFISS-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 # ; RV64-ZICFISS-NEXT: addi sp, sp, -16 ; RV64-ZICFISS-NEXT: .cfi_def_cfa_offset 16 ; RV64-ZICFISS-NEXT: sd ra, 8(sp) # 8-byte Folded Spill @@ -121,7 +123,9 @@ define i32 @f3() shadowcallstack { ; RV64-ZICFISS-NEXT: .cfi_restore ra ; RV64-ZICFISS-NEXT: addi sp, sp, 16 ; RV64-ZICFISS-NEXT: .cfi_def_cfa_offset 0 -; RV64-ZICFISS-NEXT: sspopchk ra +; RV64-ZICFISS-NEXT: ld ra, -8(gp) +; RV64-ZICFISS-NEXT: addi gp, gp, -8 +; RV64-ZICFISS-NEXT: .cfi_restore gp ; RV64-ZICFISS-NEXT: ret %res = call i32 @bar() %res1 = add i32 %res, 1 @@ -211,7 +215,9 @@ define i32 @f4() shadowcallstack { ; ; RV32-ZICFISS-LABEL: f4: ; RV32-ZICFISS: # %bb.0: -; RV32-ZICFISS-NEXT: sspush ra +; RV32-ZICFISS-NEXT: addi gp, gp, 4 +; RV32-ZICFISS-NEXT: sw ra, -4(gp) +; RV32-ZICFISS-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c # ; RV32-ZICFISS-NEXT: addi sp, sp, -16 ; RV32-ZICFISS-NEXT: .cfi_def_cfa_offset 16 ; RV32-ZICFISS-NEXT: sw ra, 12(sp) # 4-byte Folded Spill @@ -242,12 +248,16 @@ define i32 @f4() shadowcallstack { ; RV32-ZICFISS-NEXT: .cfi_restore s2 ; RV32-ZICFISS-NEXT: addi sp, sp, 16 ; RV32-ZICFISS-NEXT: .cfi_def_cfa_offset 0 -; RV32-ZICFISS-NEXT: sspopchk ra +; RV32-ZICFISS-NEXT: lw ra, -4(gp) +; RV32-ZICFISS-NEXT: addi gp, gp, -4 +; RV32-ZICFISS-NEXT: .cfi_restore gp ; RV32-ZICFISS-NEXT: ret ; ; RV64-ZICFISS-LABEL: f4: ; RV64-ZICFISS: # %bb.0: -; RV64-ZICFISS-NEXT: sspush ra +; RV64-ZICFISS-NEXT: addi gp, gp, 8 +; RV64-ZICFISS-NEXT: sd ra, -8(gp) +; RV64-ZICFISS-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 # ; RV64-ZICFISS-NEXT: addi sp, sp, -32 ; RV64-ZICFISS-NEXT: .cfi_def_cfa_offset 32 ; RV64-ZICFISS-NEXT: sd ra, 24(sp) # 8-byte Folded Spill @@ -278,7 +288,9 @@ define i32 @f4() shadowcallstack { ; RV64-ZICFISS-NEXT: .cfi_restore s2 ; RV64-ZICFISS-NEXT: addi sp, sp, 32 ; RV64-ZICFISS-NEXT: .cfi_def_cfa_offset 0 -; RV64-ZICFISS-NEXT: sspopchk ra +; RV64-ZICFISS-NEXT: ld ra, -8(gp) +; RV64-ZICFISS-NEXT: addi gp, gp, -8 +; RV64-ZICFISS-NEXT: .cfi_restore gp ; RV64-ZICFISS-NEXT: ret %res1 = call i32 @bar() %res2 = call i32 @bar() @@ -319,16 +331,642 @@ define i32 @f5() shadowcallstack nounwind { ; ; RV32-ZICFISS-LABEL: f5: ; RV32-ZICFISS: # %bb.0: +; RV32-ZICFISS-NEXT: addi gp, gp, 4 +; RV32-ZICFISS-NEXT: sw ra, -4(gp) +; RV32-ZICFISS-NEXT: addi sp, sp, -16 +; RV32-ZICFISS-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-ZICFISS-NEXT: call bar +; RV32-ZICFISS-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-ZICFISS-NEXT: addi sp, sp, 16 +; RV32-ZICFISS-NEXT: lw ra, -4(gp) +; RV32-ZICFISS-NEXT: addi gp, gp, -4 +; RV32-ZICFISS-NEXT: ret +; +; RV64-ZICFISS-LABEL: f5: +; RV64-ZICFISS: # %bb.0: +; RV64-ZICFISS-NEXT: addi gp, gp, 8 +; RV64-ZICFISS-NEXT: sd ra, -8(gp) +; RV64-ZICFISS-NEXT: addi sp, sp, -16 +; RV64-ZICFISS-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64-ZICFISS-NEXT: call bar +; RV64-ZICFISS-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64-ZICFISS-NEXT: addi sp, sp, 16 +; RV64-ZICFISS-NEXT: ld ra, -8(gp) +; RV64-ZICFISS-NEXT: addi gp, gp, -8 +; RV64-ZICFISS-NEXT: ret + %res = call i32 @bar() + %res1 = add i32 %res, 1 + ret i32 %res +} + +define void @f1_hw() "hw-shadow-stack" { +; RV32-LABEL: f1_hw: +; RV32: # %bb.0: +; RV32-NEXT: ret +; +; RV64-LABEL: f1_hw: +; RV64: # %bb.0: +; RV64-NEXT: ret +; +; RV32-ZICFISS-LABEL: f1_hw: +; RV32-ZICFISS: # %bb.0: +; RV32-ZICFISS-NEXT: ret +; +; RV64-ZICFISS-LABEL: f1_hw: +; RV64-ZICFISS: # %bb.0: +; RV64-ZICFISS-NEXT: ret + ret void +} + +define void @f2_hw() "hw-shadow-stack" { +; RV32-LABEL: f2_hw: +; RV32: # %bb.0: +; RV32-NEXT: tail foo +; +; RV64-LABEL: f2_hw: +; RV64: # %bb.0: +; RV64-NEXT: tail foo +; +; RV32-ZICFISS-LABEL: f2_hw: +; RV32-ZICFISS: # %bb.0: +; RV32-ZICFISS-NEXT: tail foo +; +; RV64-ZICFISS-LABEL: f2_hw: +; RV64-ZICFISS: # %bb.0: +; RV64-ZICFISS-NEXT: tail foo + tail call void @foo() + ret void +} + +define i32 @f3_hw() "hw-shadow-stack" { +; RV32-LABEL: f3_hw: +; RV32: # %bb.0: +; RV32-NEXT: addi sp, sp, -16 +; RV32-NEXT: .cfi_def_cfa_offset 16 +; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-NEXT: .cfi_offset ra, -4 +; RV32-NEXT: call bar +; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-NEXT: .cfi_restore ra +; RV32-NEXT: addi sp, sp, 16 +; RV32-NEXT: .cfi_def_cfa_offset 0 +; RV32-NEXT: ret +; +; RV64-LABEL: f3_hw: +; RV64: # %bb.0: +; RV64-NEXT: addi sp, sp, -16 +; RV64-NEXT: .cfi_def_cfa_offset 16 +; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64-NEXT: .cfi_offset ra, -8 +; RV64-NEXT: call bar +; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64-NEXT: .cfi_restore ra +; RV64-NEXT: addi sp, sp, 16 +; RV64-NEXT: .cfi_def_cfa_offset 0 +; RV64-NEXT: ret +; +; RV32-ZICFISS-LABEL: f3_hw: +; RV32-ZICFISS: # %bb.0: ; RV32-ZICFISS-NEXT: sspush ra ; RV32-ZICFISS-NEXT: addi sp, sp, -16 +; RV32-ZICFISS-NEXT: .cfi_def_cfa_offset 16 ; RV32-ZICFISS-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-ZICFISS-NEXT: .cfi_offset ra, -4 ; RV32-ZICFISS-NEXT: call bar ; RV32-ZICFISS-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-ZICFISS-NEXT: .cfi_restore ra ; RV32-ZICFISS-NEXT: addi sp, sp, 16 +; RV32-ZICFISS-NEXT: .cfi_def_cfa_offset 0 ; RV32-ZICFISS-NEXT: sspopchk ra ; RV32-ZICFISS-NEXT: ret ; -; RV64-ZICFISS-LABEL: f5: +; RV64-ZICFISS-LABEL: f3_hw: +; RV64-ZICFISS: # %bb.0: +; RV64-ZICFISS-NEXT: sspush ra +; RV64-ZICFISS-NEXT: addi sp, sp, -16 +; RV64-ZICFISS-NEXT: .cfi_def_cfa_offset 16 +; RV64-ZICFISS-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64-ZICFISS-NEXT: .cfi_offset ra, -8 +; RV64-ZICFISS-NEXT: call bar +; RV64-ZICFISS-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64-ZICFISS-NEXT: .cfi_restore ra +; RV64-ZICFISS-NEXT: addi sp, sp, 16 +; RV64-ZICFISS-NEXT: .cfi_def_cfa_offset 0 +; RV64-ZICFISS-NEXT: sspopchk ra +; RV64-ZICFISS-NEXT: ret + %res = call i32 @bar() + %res1 = add i32 %res, 1 + ret i32 %res +} + +define i32 @f4_hw() "hw-shadow-stack" { +; RV32-LABEL: f4_hw: +; RV32: # %bb.0: +; RV32-NEXT: addi sp, sp, -16 +; RV32-NEXT: .cfi_def_cfa_offset 16 +; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-NEXT: sw s1, 4(sp) # 4-byte Folded Spill +; RV32-NEXT: sw s2, 0(sp) # 4-byte Folded Spill +; RV32-NEXT: .cfi_offset ra, -4 +; RV32-NEXT: .cfi_offset s0, -8 +; RV32-NEXT: .cfi_offset s1, -12 +; RV32-NEXT: .cfi_offset s2, -16 +; RV32-NEXT: call bar +; RV32-NEXT: mv s0, a0 +; RV32-NEXT: call bar +; RV32-NEXT: mv s1, a0 +; RV32-NEXT: call bar +; RV32-NEXT: mv s2, a0 +; RV32-NEXT: call bar +; RV32-NEXT: add s0, s0, s1 +; RV32-NEXT: add a0, s2, a0 +; RV32-NEXT: add a0, s0, a0 +; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-NEXT: lw s1, 4(sp) # 4-byte Folded Reload +; RV32-NEXT: lw s2, 0(sp) # 4-byte Folded Reload +; RV32-NEXT: .cfi_restore ra +; RV32-NEXT: .cfi_restore s0 +; RV32-NEXT: .cfi_restore s1 +; RV32-NEXT: .cfi_restore s2 +; RV32-NEXT: addi sp, sp, 16 +; RV32-NEXT: .cfi_def_cfa_offset 0 +; RV32-NEXT: ret +; +; RV64-LABEL: f4_hw: +; RV64: # %bb.0: +; RV64-NEXT: addi sp, sp, -32 +; RV64-NEXT: .cfi_def_cfa_offset 32 +; RV64-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-NEXT: sd s1, 8(sp) # 8-byte Folded Spill +; RV64-NEXT: sd s2, 0(sp) # 8-byte Folded Spill +; RV64-NEXT: .cfi_offset ra, -8 +; RV64-NEXT: .cfi_offset s0, -16 +; RV64-NEXT: .cfi_offset s1, -24 +; RV64-NEXT: .cfi_offset s2, -32 +; RV64-NEXT: call bar +; RV64-NEXT: mv s0, a0 +; RV64-NEXT: call bar +; RV64-NEXT: mv s1, a0 +; RV64-NEXT: call bar +; RV64-NEXT: mv s2, a0 +; RV64-NEXT: call bar +; RV64-NEXT: add s0, s0, s1 +; RV64-NEXT: add a0, s2, a0 +; RV64-NEXT: addw a0, s0, a0 +; RV64-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-NEXT: ld s1, 8(sp) # 8-byte Folded Reload +; RV64-NEXT: ld s2, 0(sp) # 8-byte Folded Reload +; RV64-NEXT: .cfi_restore ra +; RV64-NEXT: .cfi_restore s0 +; RV64-NEXT: .cfi_restore s1 +; RV64-NEXT: .cfi_restore s2 +; RV64-NEXT: addi sp, sp, 32 +; RV64-NEXT: .cfi_def_cfa_offset 0 +; RV64-NEXT: ret +; +; RV32-ZICFISS-LABEL: f4_hw: +; RV32-ZICFISS: # %bb.0: +; RV32-ZICFISS-NEXT: sspush ra +; RV32-ZICFISS-NEXT: addi sp, sp, -16 +; RV32-ZICFISS-NEXT: .cfi_def_cfa_offset 16 +; RV32-ZICFISS-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-ZICFISS-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-ZICFISS-NEXT: sw s1, 4(sp) # 4-byte Folded Spill +; RV32-ZICFISS-NEXT: sw s2, 0(sp) # 4-byte Folded Spill +; RV32-ZICFISS-NEXT: .cfi_offset ra, -4 +; RV32-ZICFISS-NEXT: .cfi_offset s0, -8 +; RV32-ZICFISS-NEXT: .cfi_offset s1, -12 +; RV32-ZICFISS-NEXT: .cfi_offset s2, -16 +; RV32-ZICFISS-NEXT: call bar +; RV32-ZICFISS-NEXT: mv s0, a0 +; RV32-ZICFISS-NEXT: call bar +; RV32-ZICFISS-NEXT: mv s1, a0 +; RV32-ZICFISS-NEXT: call bar +; RV32-ZICFISS-NEXT: mv s2, a0 +; RV32-ZICFISS-NEXT: call bar +; RV32-ZICFISS-NEXT: add s0, s0, s1 +; RV32-ZICFISS-NEXT: add a0, s2, a0 +; RV32-ZICFISS-NEXT: add a0, s0, a0 +; RV32-ZICFISS-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-ZICFISS-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-ZICFISS-NEXT: lw s1, 4(sp) # 4-byte Folded Reload +; RV32-ZICFISS-NEXT: lw s2, 0(sp) # 4-byte Folded Reload +; RV32-ZICFISS-NEXT: .cfi_restore ra +; RV32-ZICFISS-NEXT: .cfi_restore s0 +; RV32-ZICFISS-NEXT: .cfi_restore s1 +; RV32-ZICFISS-NEXT: .cfi_restore s2 +; RV32-ZICFISS-NEXT: addi sp, sp, 16 +; RV32-ZICFISS-NEXT: .cfi_def_cfa_offset 0 +; RV32-ZICFISS-NEXT: sspopchk ra +; RV32-ZICFISS-NEXT: ret +; +; RV64-ZICFISS-LABEL: f4_hw: +; RV64-ZICFISS: # %bb.0: +; RV64-ZICFISS-NEXT: sspush ra +; RV64-ZICFISS-NEXT: addi sp, sp, -32 +; RV64-ZICFISS-NEXT: .cfi_def_cfa_offset 32 +; RV64-ZICFISS-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-ZICFISS-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-ZICFISS-NEXT: sd s1, 8(sp) # 8-byte Folded Spill +; RV64-ZICFISS-NEXT: sd s2, 0(sp) # 8-byte Folded Spill +; RV64-ZICFISS-NEXT: .cfi_offset ra, -8 +; RV64-ZICFISS-NEXT: .cfi_offset s0, -16 +; RV64-ZICFISS-NEXT: .cfi_offset s1, -24 +; RV64-ZICFISS-NEXT: .cfi_offset s2, -32 +; RV64-ZICFISS-NEXT: call bar +; RV64-ZICFISS-NEXT: mv s0, a0 +; RV64-ZICFISS-NEXT: call bar +; RV64-ZICFISS-NEXT: mv s1, a0 +; RV64-ZICFISS-NEXT: call bar +; RV64-ZICFISS-NEXT: mv s2, a0 +; RV64-ZICFISS-NEXT: call bar +; RV64-ZICFISS-NEXT: add s0, s0, s1 +; RV64-ZICFISS-NEXT: add a0, s2, a0 +; RV64-ZICFISS-NEXT: addw a0, s0, a0 +; RV64-ZICFISS-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-ZICFISS-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-ZICFISS-NEXT: ld s1, 8(sp) # 8-byte Folded Reload +; RV64-ZICFISS-NEXT: ld s2, 0(sp) # 8-byte Folded Reload +; RV64-ZICFISS-NEXT: .cfi_restore ra +; RV64-ZICFISS-NEXT: .cfi_restore s0 +; RV64-ZICFISS-NEXT: .cfi_restore s1 +; RV64-ZICFISS-NEXT: .cfi_restore s2 +; RV64-ZICFISS-NEXT: addi sp, sp, 32 +; RV64-ZICFISS-NEXT: .cfi_def_cfa_offset 0 +; RV64-ZICFISS-NEXT: sspopchk ra +; RV64-ZICFISS-NEXT: ret + %res1 = call i32 @bar() + %res2 = call i32 @bar() + %res3 = call i32 @bar() + %res4 = call i32 @bar() + %res12 = add i32 %res1, %res2 + %res34 = add i32 %res3, %res4 + %res1234 = add i32 %res12, %res34 + ret i32 %res1234 +} + +define i32 @f5_hw() "hw-shadow-stack" nounwind { +; RV32-LABEL: f5_hw: +; RV32: # %bb.0: +; RV32-NEXT: addi sp, sp, -16 +; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-NEXT: call bar +; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-NEXT: addi sp, sp, 16 +; RV32-NEXT: ret +; +; RV64-LABEL: f5_hw: +; RV64: # %bb.0: +; RV64-NEXT: addi sp, sp, -16 +; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64-NEXT: call bar +; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64-NEXT: addi sp, sp, 16 +; RV64-NEXT: ret +; +; RV32-ZICFISS-LABEL: f5_hw: +; RV32-ZICFISS: # %bb.0: +; RV32-ZICFISS-NEXT: sspush ra +; RV32-ZICFISS-NEXT: addi sp, sp, -16 +; RV32-ZICFISS-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-ZICFISS-NEXT: call bar +; RV32-ZICFISS-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-ZICFISS-NEXT: addi sp, sp, 16 +; RV32-ZICFISS-NEXT: sspopchk ra +; RV32-ZICFISS-NEXT: ret +; +; RV64-ZICFISS-LABEL: f5_hw: +; RV64-ZICFISS: # %bb.0: +; RV64-ZICFISS-NEXT: sspush ra +; RV64-ZICFISS-NEXT: addi sp, sp, -16 +; RV64-ZICFISS-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64-ZICFISS-NEXT: call bar +; RV64-ZICFISS-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64-ZICFISS-NEXT: addi sp, sp, 16 +; RV64-ZICFISS-NEXT: sspopchk ra +; RV64-ZICFISS-NEXT: ret + %res = call i32 @bar() + %res1 = add i32 %res, 1 + ret i32 %res +} + +define void @f1_both() "hw-shadow-stack" shadowcallstack { +; RV32-LABEL: f1_both: +; RV32: # %bb.0: +; RV32-NEXT: ret +; +; RV64-LABEL: f1_both: +; RV64: # %bb.0: +; RV64-NEXT: ret +; +; RV32-ZICFISS-LABEL: f1_both: +; RV32-ZICFISS: # %bb.0: +; RV32-ZICFISS-NEXT: ret +; +; RV64-ZICFISS-LABEL: f1_both: +; RV64-ZICFISS: # %bb.0: +; RV64-ZICFISS-NEXT: ret + ret void +} + +define void @f2_both() "hw-shadow-stack" shadowcallstack { +; RV32-LABEL: f2_both: +; RV32: # %bb.0: +; RV32-NEXT: tail foo +; +; RV64-LABEL: f2_both: +; RV64: # %bb.0: +; RV64-NEXT: tail foo +; +; RV32-ZICFISS-LABEL: f2_both: +; RV32-ZICFISS: # %bb.0: +; RV32-ZICFISS-NEXT: tail foo +; +; RV64-ZICFISS-LABEL: f2_both: +; RV64-ZICFISS: # %bb.0: +; RV64-ZICFISS-NEXT: tail foo + tail call void @foo() + ret void +} + +define i32 @f3_both() "hw-shadow-stack" shadowcallstack { +; RV32-LABEL: f3_both: +; RV32: # %bb.0: +; RV32-NEXT: addi gp, gp, 4 +; RV32-NEXT: sw ra, -4(gp) +; RV32-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c # +; RV32-NEXT: addi sp, sp, -16 +; RV32-NEXT: .cfi_def_cfa_offset 16 +; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-NEXT: .cfi_offset ra, -4 +; RV32-NEXT: call bar +; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-NEXT: .cfi_restore ra +; RV32-NEXT: addi sp, sp, 16 +; RV32-NEXT: .cfi_def_cfa_offset 0 +; RV32-NEXT: lw ra, -4(gp) +; RV32-NEXT: addi gp, gp, -4 +; RV32-NEXT: .cfi_restore gp +; RV32-NEXT: ret +; +; RV64-LABEL: f3_both: +; RV64: # %bb.0: +; RV64-NEXT: addi gp, gp, 8 +; RV64-NEXT: sd ra, -8(gp) +; RV64-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 # +; RV64-NEXT: addi sp, sp, -16 +; RV64-NEXT: .cfi_def_cfa_offset 16 +; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64-NEXT: .cfi_offset ra, -8 +; RV64-NEXT: call bar +; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64-NEXT: .cfi_restore ra +; RV64-NEXT: addi sp, sp, 16 +; RV64-NEXT: .cfi_def_cfa_offset 0 +; RV64-NEXT: ld ra, -8(gp) +; RV64-NEXT: addi gp, gp, -8 +; RV64-NEXT: .cfi_restore gp +; RV64-NEXT: ret +; +; RV32-ZICFISS-LABEL: f3_both: +; RV32-ZICFISS: # %bb.0: +; RV32-ZICFISS-NEXT: sspush ra +; RV32-ZICFISS-NEXT: addi sp, sp, -16 +; RV32-ZICFISS-NEXT: .cfi_def_cfa_offset 16 +; RV32-ZICFISS-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-ZICFISS-NEXT: .cfi_offset ra, -4 +; RV32-ZICFISS-NEXT: call bar +; RV32-ZICFISS-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-ZICFISS-NEXT: .cfi_restore ra +; RV32-ZICFISS-NEXT: addi sp, sp, 16 +; RV32-ZICFISS-NEXT: .cfi_def_cfa_offset 0 +; RV32-ZICFISS-NEXT: sspopchk ra +; RV32-ZICFISS-NEXT: ret +; +; RV64-ZICFISS-LABEL: f3_both: +; RV64-ZICFISS: # %bb.0: +; RV64-ZICFISS-NEXT: sspush ra +; RV64-ZICFISS-NEXT: addi sp, sp, -16 +; RV64-ZICFISS-NEXT: .cfi_def_cfa_offset 16 +; RV64-ZICFISS-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64-ZICFISS-NEXT: .cfi_offset ra, -8 +; RV64-ZICFISS-NEXT: call bar +; RV64-ZICFISS-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64-ZICFISS-NEXT: .cfi_restore ra +; RV64-ZICFISS-NEXT: addi sp, sp, 16 +; RV64-ZICFISS-NEXT: .cfi_def_cfa_offset 0 +; RV64-ZICFISS-NEXT: sspopchk ra +; RV64-ZICFISS-NEXT: ret + %res = call i32 @bar() + %res1 = add i32 %res, 1 + ret i32 %res +} + +define i32 @f4_both() "hw-shadow-stack" shadowcallstack { +; RV32-LABEL: f4_both: +; RV32: # %bb.0: +; RV32-NEXT: addi gp, gp, 4 +; RV32-NEXT: sw ra, -4(gp) +; RV32-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c # +; RV32-NEXT: addi sp, sp, -16 +; RV32-NEXT: .cfi_def_cfa_offset 16 +; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-NEXT: sw s1, 4(sp) # 4-byte Folded Spill +; RV32-NEXT: sw s2, 0(sp) # 4-byte Folded Spill +; RV32-NEXT: .cfi_offset ra, -4 +; RV32-NEXT: .cfi_offset s0, -8 +; RV32-NEXT: .cfi_offset s1, -12 +; RV32-NEXT: .cfi_offset s2, -16 +; RV32-NEXT: call bar +; RV32-NEXT: mv s0, a0 +; RV32-NEXT: call bar +; RV32-NEXT: mv s1, a0 +; RV32-NEXT: call bar +; RV32-NEXT: mv s2, a0 +; RV32-NEXT: call bar +; RV32-NEXT: add s0, s0, s1 +; RV32-NEXT: add a0, s2, a0 +; RV32-NEXT: add a0, s0, a0 +; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-NEXT: lw s1, 4(sp) # 4-byte Folded Reload +; RV32-NEXT: lw s2, 0(sp) # 4-byte Folded Reload +; RV32-NEXT: .cfi_restore ra +; RV32-NEXT: .cfi_restore s0 +; RV32-NEXT: .cfi_restore s1 +; RV32-NEXT: .cfi_restore s2 +; RV32-NEXT: addi sp, sp, 16 +; RV32-NEXT: .cfi_def_cfa_offset 0 +; RV32-NEXT: lw ra, -4(gp) +; RV32-NEXT: addi gp, gp, -4 +; RV32-NEXT: .cfi_restore gp +; RV32-NEXT: ret +; +; RV64-LABEL: f4_both: +; RV64: # %bb.0: +; RV64-NEXT: addi gp, gp, 8 +; RV64-NEXT: sd ra, -8(gp) +; RV64-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 # +; RV64-NEXT: addi sp, sp, -32 +; RV64-NEXT: .cfi_def_cfa_offset 32 +; RV64-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-NEXT: sd s1, 8(sp) # 8-byte Folded Spill +; RV64-NEXT: sd s2, 0(sp) # 8-byte Folded Spill +; RV64-NEXT: .cfi_offset ra, -8 +; RV64-NEXT: .cfi_offset s0, -16 +; RV64-NEXT: .cfi_offset s1, -24 +; RV64-NEXT: .cfi_offset s2, -32 +; RV64-NEXT: call bar +; RV64-NEXT: mv s0, a0 +; RV64-NEXT: call bar +; RV64-NEXT: mv s1, a0 +; RV64-NEXT: call bar +; RV64-NEXT: mv s2, a0 +; RV64-NEXT: call bar +; RV64-NEXT: add s0, s0, s1 +; RV64-NEXT: add a0, s2, a0 +; RV64-NEXT: addw a0, s0, a0 +; RV64-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-NEXT: ld s1, 8(sp) # 8-byte Folded Reload +; RV64-NEXT: ld s2, 0(sp) # 8-byte Folded Reload +; RV64-NEXT: .cfi_restore ra +; RV64-NEXT: .cfi_restore s0 +; RV64-NEXT: .cfi_restore s1 +; RV64-NEXT: .cfi_restore s2 +; RV64-NEXT: addi sp, sp, 32 +; RV64-NEXT: .cfi_def_cfa_offset 0 +; RV64-NEXT: ld ra, -8(gp) +; RV64-NEXT: addi gp, gp, -8 +; RV64-NEXT: .cfi_restore gp +; RV64-NEXT: ret +; +; RV32-ZICFISS-LABEL: f4_both: +; RV32-ZICFISS: # %bb.0: +; RV32-ZICFISS-NEXT: sspush ra +; RV32-ZICFISS-NEXT: addi sp, sp, -16 +; RV32-ZICFISS-NEXT: .cfi_def_cfa_offset 16 +; RV32-ZICFISS-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-ZICFISS-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-ZICFISS-NEXT: sw s1, 4(sp) # 4-byte Folded Spill +; RV32-ZICFISS-NEXT: sw s2, 0(sp) # 4-byte Folded Spill +; RV32-ZICFISS-NEXT: .cfi_offset ra, -4 +; RV32-ZICFISS-NEXT: .cfi_offset s0, -8 +; RV32-ZICFISS-NEXT: .cfi_offset s1, -12 +; RV32-ZICFISS-NEXT: .cfi_offset s2, -16 +; RV32-ZICFISS-NEXT: call bar +; RV32-ZICFISS-NEXT: mv s0, a0 +; RV32-ZICFISS-NEXT: call bar +; RV32-ZICFISS-NEXT: mv s1, a0 +; RV32-ZICFISS-NEXT: call bar +; RV32-ZICFISS-NEXT: mv s2, a0 +; RV32-ZICFISS-NEXT: call bar +; RV32-ZICFISS-NEXT: add s0, s0, s1 +; RV32-ZICFISS-NEXT: add a0, s2, a0 +; RV32-ZICFISS-NEXT: add a0, s0, a0 +; RV32-ZICFISS-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-ZICFISS-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-ZICFISS-NEXT: lw s1, 4(sp) # 4-byte Folded Reload +; RV32-ZICFISS-NEXT: lw s2, 0(sp) # 4-byte Folded Reload +; RV32-ZICFISS-NEXT: .cfi_restore ra +; RV32-ZICFISS-NEXT: .cfi_restore s0 +; RV32-ZICFISS-NEXT: .cfi_restore s1 +; RV32-ZICFISS-NEXT: .cfi_restore s2 +; RV32-ZICFISS-NEXT: addi sp, sp, 16 +; RV32-ZICFISS-NEXT: .cfi_def_cfa_offset 0 +; RV32-ZICFISS-NEXT: sspopchk ra +; RV32-ZICFISS-NEXT: ret +; +; RV64-ZICFISS-LABEL: f4_both: +; RV64-ZICFISS: # %bb.0: +; RV64-ZICFISS-NEXT: sspush ra +; RV64-ZICFISS-NEXT: addi sp, sp, -32 +; RV64-ZICFISS-NEXT: .cfi_def_cfa_offset 32 +; RV64-ZICFISS-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-ZICFISS-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-ZICFISS-NEXT: sd s1, 8(sp) # 8-byte Folded Spill +; RV64-ZICFISS-NEXT: sd s2, 0(sp) # 8-byte Folded Spill +; RV64-ZICFISS-NEXT: .cfi_offset ra, -8 +; RV64-ZICFISS-NEXT: .cfi_offset s0, -16 +; RV64-ZICFISS-NEXT: .cfi_offset s1, -24 +; RV64-ZICFISS-NEXT: .cfi_offset s2, -32 +; RV64-ZICFISS-NEXT: call bar +; RV64-ZICFISS-NEXT: mv s0, a0 +; RV64-ZICFISS-NEXT: call bar +; RV64-ZICFISS-NEXT: mv s1, a0 +; RV64-ZICFISS-NEXT: call bar +; RV64-ZICFISS-NEXT: mv s2, a0 +; RV64-ZICFISS-NEXT: call bar +; RV64-ZICFISS-NEXT: add s0, s0, s1 +; RV64-ZICFISS-NEXT: add a0, s2, a0 +; RV64-ZICFISS-NEXT: addw a0, s0, a0 +; RV64-ZICFISS-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-ZICFISS-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-ZICFISS-NEXT: ld s1, 8(sp) # 8-byte Folded Reload +; RV64-ZICFISS-NEXT: ld s2, 0(sp) # 8-byte Folded Reload +; RV64-ZICFISS-NEXT: .cfi_restore ra +; RV64-ZICFISS-NEXT: .cfi_restore s0 +; RV64-ZICFISS-NEXT: .cfi_restore s1 +; RV64-ZICFISS-NEXT: .cfi_restore s2 +; RV64-ZICFISS-NEXT: addi sp, sp, 32 +; RV64-ZICFISS-NEXT: .cfi_def_cfa_offset 0 +; RV64-ZICFISS-NEXT: sspopchk ra +; RV64-ZICFISS-NEXT: ret + %res1 = call i32 @bar() + %res2 = call i32 @bar() + %res3 = call i32 @bar() + %res4 = call i32 @bar() + %res12 = add i32 %res1, %res2 + %res34 = add i32 %res3, %res4 + %res1234 = add i32 %res12, %res34 + ret i32 %res1234 +} + +define i32 @f5_both() "hw-shadow-stack" shadowcallstack nounwind { +; RV32-LABEL: f5_both: +; RV32: # %bb.0: +; RV32-NEXT: addi gp, gp, 4 +; RV32-NEXT: sw ra, -4(gp) +; RV32-NEXT: addi sp, sp, -16 +; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-NEXT: call bar +; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-NEXT: addi sp, sp, 16 +; RV32-NEXT: lw ra, -4(gp) +; RV32-NEXT: addi gp, gp, -4 +; RV32-NEXT: ret +; +; RV64-LABEL: f5_both: +; RV64: # %bb.0: +; RV64-NEXT: addi gp, gp, 8 +; RV64-NEXT: sd ra, -8(gp) +; RV64-NEXT: addi sp, sp, -16 +; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64-NEXT: call bar +; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64-NEXT: addi sp, sp, 16 +; RV64-NEXT: ld ra, -8(gp) +; RV64-NEXT: addi gp, gp, -8 +; RV64-NEXT: ret +; +; RV32-ZICFISS-LABEL: f5_both: +; RV32-ZICFISS: # %bb.0: +; RV32-ZICFISS-NEXT: sspush ra +; RV32-ZICFISS-NEXT: addi sp, sp, -16 +; RV32-ZICFISS-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-ZICFISS-NEXT: call bar +; RV32-ZICFISS-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-ZICFISS-NEXT: addi sp, sp, 16 +; RV32-ZICFISS-NEXT: sspopchk ra +; RV32-ZICFISS-NEXT: ret +; +; RV64-ZICFISS-LABEL: f5_both: ; RV64-ZICFISS: # %bb.0: ; RV64-ZICFISS-NEXT: sspush ra ; RV64-ZICFISS-NEXT: addi sp, sp, -16