[clang] aa1d269 - [CodeGen][RISCV] Change Shadow Call Stack Register to X3

Paul Kirth via cfe-commits cfe-commits at lists.llvm.org
Wed Apr 12 14:06:31 PDT 2023


Author: Paul Kirth
Date: 2023-04-12T21:06:22Z
New Revision: aa1d2693c25622ea4a8ee2b622ba2a617e18ef88

URL: https://github.com/llvm/llvm-project/commit/aa1d2693c25622ea4a8ee2b622ba2a617e18ef88
DIFF: https://github.com/llvm/llvm-project/commit/aa1d2693c25622ea4a8ee2b622ba2a617e18ef88.diff

LOG: [CodeGen][RISCV] Change Shadow Call Stack Register to X3

ShadowCallStack implementation uses s2 register on RISC-V, but that
choice is problematic for reasons described in:

https://lists.riscv.org/g/sig-toolchains/message/544,
https://github.com/riscv-non-isa/riscv-elf-psabi-doc/issues/370, and
https://github.com/google/android-riscv64/issues/72

The concern over the register choice was also brought up in
https://reviews.llvm.org/D84414.

https://reviews.llvm.org/D84414#2228666 said:

```
  "If the register choice is the only concern about this work, then I think
  we can probably land it as-is and fixup the register choice if we see
  major drawbacks later. Yes, it's an ABI issue, but on the other hand the
  shadow call stack is not a standard ABI anyway.""
```

Since we have now found a sufficient reason to fixup the register
choice, we should go ahead and update the implementation. We propose
using x3(gp) which is now the platform register in the RISC-V ABI.

Reviewed By: asb, hiraditya, mcgrathr, craig.topper

Differential Revision: https://reviews.llvm.org/D146463

Added: 
    llvm/test/CodeGen/RISCV/saverestore-scs.ll

Modified: 
    clang/docs/ShadowCallStack.rst
    clang/lib/Driver/SanitizerArgs.cpp
    clang/test/Driver/sanitizer-ld.c
    compiler-rt/test/shadowcallstack/lit.cfg.py
    llvm/docs/ReleaseNotes.rst
    llvm/include/llvm/TargetParser/RISCVTargetParser.h
    llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp
    llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
    llvm/lib/Target/RISCV/RISCVSubtarget.cpp
    llvm/lib/TargetParser/RISCVTargetParser.cpp
    llvm/test/CodeGen/RISCV/reserved-regs.ll
    llvm/test/CodeGen/RISCV/shadowcallstack.ll

Removed: 
    


################################################################################
diff  --git a/clang/docs/ShadowCallStack.rst b/clang/docs/ShadowCallStack.rst
index b1ab4c6e8b239..04c04d259d7dc 100644
--- a/clang/docs/ShadowCallStack.rst
+++ b/clang/docs/ShadowCallStack.rst
@@ -57,24 +57,27 @@ compiled application or the operating system. Integrating the runtime into
 the operating system should be preferred since otherwise all thread creation
 and destruction would need to be intercepted by the application.
 
-The instrumentation makes use of the platform register ``x18``.  On some
-platforms, ``x18`` is reserved, and on others, it is designated as a scratch
-register.  This generally means that any code that may run on the same thread
-as code compiled with ShadowCallStack must either target one of the platforms
-whose ABI reserves ``x18`` (currently Android, Darwin, Fuchsia and Windows)
-or be compiled with the flag ``-ffixed-x18``. If absolutely necessary, code
-compiled without ``-ffixed-x18`` may be run on the same thread as code that
-uses ShadowCallStack by saving the register value temporarily on the stack
-(`example in Android`_) but this should be done with care since it risks
-leaking the shadow call stack address.
+The instrumentation makes use of the platform register ``x18`` on AArch64 and
+``x3`` (``gp``) on RISC-V. For simplicity we will refer to this as the
+``SCSReg``. On some platforms, ``SCSReg`` is reserved, and on others, it is
+designated as a scratch register.  This generally means that any code that may
+run on the same thread as code compiled with ShadowCallStack must either target
+one of the platforms whose ABI reserves ``SCSReg`` (currently Android, Darwin,
+Fuchsia and Windows) or be compiled with a flag to reserve that register (e.g.,
+``-ffixed-x18``). If absolutely necessary, code compiled without reserving the
+register may be run on the same thread as code that uses ShadowCallStack by
+saving the register value temporarily on the stack (`example in Android`_) but
+this should be done with care since it risks leaking the shadow call stack
+address.
 
 .. _`example in Android`: https://android-review.googlesource.com/c/platform/frameworks/base/+/803717
 
-Because of the use of register ``x18``, the ShadowCallStack feature is
-incompatible with any other feature that may use ``x18``. However, there
-is no inherent reason why ShadowCallStack needs to use register ``x18``
-specifically; in principle, a platform could choose to reserve and use another
-register for ShadowCallStack, but this would be incompatible with the AAPCS64.
+Because it requires a dedicated register, the ShadowCallStack feature is
+incompatible with any other feature that may use ``SCSReg``. However, there is
+no inherent reason why ShadowCallStack needs to use a specific register; in
+principle, a platform could choose to reserve and use another register for
+ShadowCallStack, but this would be incompatible with the ABI standards
+published in AAPCS64 and the RISC-V psABI.
 
 Special unwind information is required on functions that are compiled
 with ShadowCallStack and that may be unwound, i.e. functions compiled with
@@ -91,7 +94,7 @@ ShadowCallStack is intended to be a stronger alternative to
 ``-fstack-protector``. It protects from non-linear overflows and arbitrary
 memory writes to the return address slot.
 
-The instrumentation makes use of the ``x18`` register to reference the shadow
+The instrumentation makes use of the ``SCSReg`` register to reference the shadow
 call stack, meaning that references to the shadow call stack do not have
 to be stored in memory. This makes it possible to implement a runtime that
 avoids exposing the address of the shadow call stack to attackers that can
@@ -120,11 +123,11 @@ guard regions that can be allocated.
 
 The runtime will need the address of the shadow call stack in order to
 deallocate it when destroying the thread. If the entire program is compiled
-with ``-ffixed-x18``, this is trivial: the address can be derived from the
-value stored in ``x18`` (e.g. by masking out the lower bits). If a guard
+with ``SCSReg`` reserved, this is trivial: the address can be derived from the
+value stored in ``SCSReg`` (e.g. by masking out the lower bits). If a guard
 region is used, the address of the start of the guard region could then be
 stored at the start of the shadow call stack itself. But if it is possible
-for code compiled without ``-ffixed-x18`` to run on a thread managed by the
+for code compiled without reserving ``SCSReg`` to run on a thread managed by the
 runtime, which is the case on Android for example, the address must be stored
 somewhere else instead. On Android we store the address of the start of the
 guard region in TLS and deallocate the entire guard region including the
@@ -133,7 +136,7 @@ the address of the start of the guard region is already somewhat guessable.
 
 One way in which the address of the shadow call stack could leak is in the
 ``jmp_buf`` data structure used by ``setjmp`` and ``longjmp``. The Android
-runtime `avoids this`_ by only storing the low bits of ``x18`` in the
+runtime `avoids this`_ by only storing the low bits of ``SCSReg`` in the
 ``jmp_buf``, which requires the address of the shadow call stack to be
 aligned to its size.
 
@@ -146,9 +149,11 @@ protected from return address overwrites even without ShadowCallStack.
 Usage
 =====
 
-To enable ShadowCallStack, just pass the ``-fsanitize=shadow-call-stack``
-flag to both compile and link command lines. On aarch64, you also need to pass
-``-ffixed-x18`` unless your target already reserves ``x18``.
+To enable ShadowCallStack, just pass the ``-fsanitize=shadow-call-stack`` flag
+to both compile and link command lines. On aarch64, you also need to pass
+``-ffixed-x18`` unless your target already reserves ``x18``. On RISC-V, ``x3``
+(``gp``) is always reserved. It is, however, important to disable GP relaxation
+in the linker. This can be done with the ``--no-relax-gp`` flag in GNU ld.
 
 Low-level API
 -------------

diff  --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp
index 299d4adf3333a..3f5b67e5f9b01 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -13,6 +13,7 @@
 #include "clang/Driver/Options.h"
 #include "clang/Driver/ToolChain.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/SpecialCaseList.h"
@@ -543,11 +544,8 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
         << lastArgumentForMask(D, Args, Kinds & NeedsLTO) << "-flto";
   }
 
-  if ((Kinds & SanitizerKind::ShadowCallStack) &&
-      ((TC.getTriple().isAArch64() &&
-        !llvm::AArch64::isX18ReservedByDefault(TC.getTriple())) ||
-       (TC.getTriple().isRISCV() &&
-        !llvm::RISCV::isX18ReservedByDefault(TC.getTriple()))) &&
+  if ((Kinds & SanitizerKind::ShadowCallStack) && TC.getTriple().isAArch64() &&
+      !llvm::AArch64::isX18ReservedByDefault(TC.getTriple()) &&
       !Args.hasArg(options::OPT_ffixed_x18) && DiagnoseErrors) {
     D.Diag(diag::err_drv_argument_only_allowed_with)
         << lastArgumentForMask(D, Args, Kinds & SanitizerKind::ShadowCallStack)

diff  --git a/clang/test/Driver/sanitizer-ld.c b/clang/test/Driver/sanitizer-ld.c
index 0778a96ae2350..8192672b73fce 100644
--- a/clang/test/Driver/sanitizer-ld.c
+++ b/clang/test/Driver/sanitizer-ld.c
@@ -736,12 +736,12 @@
 // RUN: %clang -fsanitize=shadow-call-stack -### %s 2>&1 \
 // RUN:     --target=riscv32-unknown-elf -fuse-ld=ld \
 // RUN:   | FileCheck --check-prefix=CHECK-SHADOWCALLSTACK-ELF-RISCV32 %s
-// CHECK-SHADOWCALLSTACK-ELF-RISCV32: '-fsanitize=shadow-call-stack' only allowed with '-ffixed-x18'
+// CHECK-SHADOWCALLSTACK-ELF-RISCV32-NOT: error:
 
 // RUN: %clang -fsanitize=shadow-call-stack -### %s 2>&1 \
 // RUN:     --target=riscv64-unknown-linux -fuse-ld=ld \
 // RUN:   | FileCheck --check-prefix=CHECK-SHADOWCALLSTACK-LINUX-RISCV64 %s
-// CHECK-SHADOWCALLSTACK-LINUX-RISCV64: '-fsanitize=shadow-call-stack' only allowed with '-ffixed-x18'
+// CHECK-SHADOWCALLSTACK-LINUX-RISCV64-NOT: error:
 
 // RUN: %clang -target riscv64-linux-android -fsanitize=shadow-call-stack %s -### 2>&1 \
 // RUN:   | FileCheck %s --check-prefix=CHECK-SHADOWCALLSTACK-ANDROID-RISCV64

diff  --git a/compiler-rt/test/shadowcallstack/lit.cfg.py b/compiler-rt/test/shadowcallstack/lit.cfg.py
index fc736af8c4fb4..062ce83ea15d7 100644
--- a/compiler-rt/test/shadowcallstack/lit.cfg.py
+++ b/compiler-rt/test/shadowcallstack/lit.cfg.py
@@ -19,5 +19,5 @@
   scs_arch_cflags += ' -ffixed-x18 '
 config.substitutions.append( ("%clang_scs ", config.clang + ' -O0 -fsanitize=shadow-call-stack ' + scs_arch_cflags + ' ') )
 
-if config.host_os not in ['Linux'] or config.target_arch not in ['aarch64']:
+if config.host_os not in ['Linux'] or config.target_arch not in ['aarch64','riscv64']:
    config.unsupported = True

diff  --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst
index 88d43a3befa5e..d747752c2a085 100644
--- a/llvm/docs/ReleaseNotes.rst
+++ b/llvm/docs/ReleaseNotes.rst
@@ -161,6 +161,11 @@ Changes to the RISC-V Backend
 * I, F, D, and A extension versions have been update to the 20191214 spec versions.
   New version I2.1, F2.2, D2.2, A2.1. This should not impact code generation.
   Immpacts versions accepted in ``-march`` and reported in ELF attributes.
+* Changed the ShadowCallStack register from ``x18`` (``s2``) to ``x3``
+  (``gp``). Note this breaks the existing non-standard ABI for ShadowCallStack
+  on RISC-V, but conforms with the new "platform register" defined in the
+  RISC-V psABI (for more details see the 
+  `psABI discussion <https://github.com/riscv-non-isa/riscv-elf-psabi-doc/issues/370>`_).
 
 Changes to the WebAssembly Backend
 ----------------------------------

diff  --git a/llvm/include/llvm/TargetParser/RISCVTargetParser.h b/llvm/include/llvm/TargetParser/RISCVTargetParser.h
index 6f6c89e80e4ec..993f653455a0d 100644
--- a/llvm/include/llvm/TargetParser/RISCVTargetParser.h
+++ b/llvm/include/llvm/TargetParser/RISCVTargetParser.h
@@ -40,8 +40,6 @@ StringRef getMArchFromMcpu(StringRef CPU);
 void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64);
 void fillValidTuneCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64);
 
-bool isX18ReservedByDefault(const Triple &TT);
-
 } // namespace RISCV
 } // namespace llvm
 

diff  --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp
index 38f75ad1f8c27..aa0664f6faae0 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp
@@ -98,7 +98,7 @@ ABI getTargetABI(StringRef ABIName) {
 MCRegister getBPReg() { return RISCV::X9; }
 
 // Returns the register holding shadow call stack pointer.
-MCRegister getSCSPReg() { return RISCV::X18; }
+MCRegister getSCSPReg() { return RISCV::X3; }
 
 } // namespace RISCVABI
 

diff  --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index 2bbb4109b6944..790b50d6163c4 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -27,8 +27,8 @@
 
 using namespace llvm;
 
-// For now we use x18, a.k.a s2, as pointer to shadow call stack.
-// User should explicitly set -ffixed-x18 and not use x18 in their asm.
+// For now we use x3, a.k.a gp, as pointer to shadow call stack.
+// User should not use x3 in their asm.
 static void emitSCSPrologue(MachineFunction &MF, MachineBasicBlock &MBB,
                             MachineBasicBlock::iterator MI,
                             const DebugLoc &DL) {
@@ -48,27 +48,12 @@ static void emitSCSPrologue(MachineFunction &MF, MachineBasicBlock &MBB,
 
   Register SCSPReg = RISCVABI::getSCSPReg();
 
-  auto &Ctx = MF.getFunction().getContext();
-  if (!STI.isRegisterReservedByUser(SCSPReg)) {
-    Ctx.diagnose(DiagnosticInfoUnsupported{
-        MF.getFunction(), "x18 not reserved by user for Shadow Call Stack."});
-    return;
-  }
-
-  const auto *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();
-  if (RVFI->useSaveRestoreLibCalls(MF)) {
-    Ctx.diagnose(DiagnosticInfoUnsupported{
-        MF.getFunction(),
-        "Shadow Call Stack cannot be combined with Save/Restore LibCalls."});
-    return;
-  }
-
   const RISCVInstrInfo *TII = STI.getInstrInfo();
   bool IsRV64 = STI.hasFeature(RISCV::Feature64Bit);
   int64_t SlotSize = STI.getXLen() / 8;
   // Store return address to shadow call stack
-  // s[w|d]  ra, 0(s2)
-  // addi    s2, s2, [4|8]
+  // s[w|d]  ra, 0(gp)
+  // addi    gp, gp, [4|8]
   BuildMI(MBB, MI, DL, TII->get(IsRV64 ? RISCV::SD : RISCV::SW))
       .addReg(RAReg)
       .addReg(SCSPReg)
@@ -83,7 +68,7 @@ static void emitSCSPrologue(MachineFunction &MF, MachineBasicBlock &MBB,
   // Emit a CFI instruction that causes SlotSize to be subtracted from the value
   // of the shadow stack pointer when unwinding past this frame.
   char DwarfSCSReg = TRI->getDwarfRegNum(SCSPReg, /*IsEH*/ true);
-  assert(DwarfSCSReg < 32 && "SCS Register should be < 32 (X18).");
+  assert(DwarfSCSReg < 32 && "SCS Register should be < 32 (X3).");
 
   char Offset = static_cast<char>(-SlotSize) & 0x7f;
   const char CFIInst[] = {
@@ -118,27 +103,12 @@ static void emitSCSEpilogue(MachineFunction &MF, MachineBasicBlock &MBB,
 
   Register SCSPReg = RISCVABI::getSCSPReg();
 
-  auto &Ctx = MF.getFunction().getContext();
-  if (!STI.isRegisterReservedByUser(SCSPReg)) {
-    Ctx.diagnose(DiagnosticInfoUnsupported{
-        MF.getFunction(), "x18 not reserved by user for Shadow Call Stack."});
-    return;
-  }
-
-  const auto *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();
-  if (RVFI->useSaveRestoreLibCalls(MF)) {
-    Ctx.diagnose(DiagnosticInfoUnsupported{
-        MF.getFunction(),
-        "Shadow Call Stack cannot be combined with Save/Restore LibCalls."});
-    return;
-  }
-
   const RISCVInstrInfo *TII = STI.getInstrInfo();
   bool IsRV64 = STI.hasFeature(RISCV::Feature64Bit);
   int64_t SlotSize = STI.getXLen() / 8;
   // Load return address from shadow call stack
-  // l[w|d]  ra, -[4|8](s2)
-  // addi    s2, s2, -[4|8]
+  // l[w|d]  ra, -[4|8](gp)
+  // addi    gp, gp, -[4|8]
   BuildMI(MBB, MI, DL, TII->get(IsRV64 ? RISCV::LD : RISCV::LW))
       .addReg(RAReg, RegState::Define)
       .addReg(SCSPReg)

diff  --git a/llvm/lib/Target/RISCV/RISCVSubtarget.cpp b/llvm/lib/Target/RISCV/RISCVSubtarget.cpp
index 9e2af55d2131b..f05753e61c363 100644
--- a/llvm/lib/Target/RISCV/RISCVSubtarget.cpp
+++ b/llvm/lib/Target/RISCV/RISCVSubtarget.cpp
@@ -83,9 +83,6 @@ RISCVSubtarget::RISCVSubtarget(const Triple &TT, StringRef CPU,
       FrameLowering(
           initializeSubtargetDependencies(TT, CPU, TuneCPU, FS, ABIName)),
       InstrInfo(*this), RegInfo(getHwMode()), TLInfo(TM, *this) {
-  if (RISCV::isX18ReservedByDefault(TT))
-    UserReservedRegister.set(RISCV::X18);
-
   CallLoweringInfo.reset(new RISCVCallLowering(*getTargetLowering()));
   Legalizer.reset(new RISCVLegalizerInfo(*this));
 

diff  --git a/llvm/lib/TargetParser/RISCVTargetParser.cpp b/llvm/lib/TargetParser/RISCVTargetParser.cpp
index e3543b90e4d25..ac726cdbb797c 100644
--- a/llvm/lib/TargetParser/RISCVTargetParser.cpp
+++ b/llvm/lib/TargetParser/RISCVTargetParser.cpp
@@ -85,10 +85,5 @@ void fillValidTuneCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64) {
 #include "llvm/TargetParser/RISCVTargetParserDef.inc"
 }
 
-bool isX18ReservedByDefault(const Triple &TT) {
-  // X18 is reserved for the ShadowCallStack ABI (even when not enabled).
-  return TT.isOSFuchsia() || TT.isAndroid();
-}
-
 } // namespace RISCV
 } // namespace llvm

diff  --git a/llvm/test/CodeGen/RISCV/reserved-regs.ll b/llvm/test/CodeGen/RISCV/reserved-regs.ll
index 68c6a6558eccc..045ffabf2ffc5 100644
--- a/llvm/test/CodeGen/RISCV/reserved-regs.ll
+++ b/llvm/test/CodeGen/RISCV/reserved-regs.ll
@@ -57,9 +57,6 @@
 ; RUN: llc -mtriple=riscv32 -mattr=+reserve-x31 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X31
 ; RUN: llc -mtriple=riscv64 -mattr=+reserve-x31 -verify-machineinstrs < %s | FileCheck %s -check-prefix=X31
 
-; RUN: llc -mtriple=riscv64-fuchsia -verify-machineinstrs < %s | FileCheck %s -check-prefix=X18
-; RUN: llc -mtriple=riscv64-linux-android -verify-machineinstrs < %s | FileCheck %s -check-prefix=X18
-
 ; This program is free to use all registers, but needs a stack pointer for
 ; spill values, so do not test for reserving the stack pointer.
 

diff  --git a/llvm/test/CodeGen/RISCV/saverestore-scs.ll b/llvm/test/CodeGen/RISCV/saverestore-scs.ll
new file mode 100644
index 0000000000000..6c3ee2c2f383f
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/saverestore-scs.ll
@@ -0,0 +1,40 @@
+;; Check that shadow call stack doesn't interfere with save/restore
+
+; RUN: llc -mtriple=riscv32 < %s | FileCheck %s -check-prefix=RV32I
+; RUN: llc -mtriple=riscv64 < %s | FileCheck %s -check-prefix=RV64I
+; RUN: llc -mtriple=riscv32 -mattr=+save-restore < %s | FileCheck %s -check-prefix=RV32I-SR
+; RUN: llc -mtriple=riscv64 -mattr=+save-restore < %s | FileCheck %s -check-prefix=RV64I-SR
+; RUN: llc -mtriple=riscv32 -mattr=+f,+save-restore -target-abi=ilp32f < %s | FileCheck %s -check-prefix=RV32I-FP-SR
+; RUN: llc -mtriple=riscv64 -mattr=+f,+d,+save-restore -target-abi=lp64d < %s | FileCheck %s -check-prefix=RV64I-FP-SR
+
+ at var2 = global [30 x i32] zeroinitializer
+
+define void @callee_scs() nounwind shadowcallstack {
+; RV32I-LABEL: callee_scs:
+; RV32I-NOT:     call t0, __riscv_save
+; RV32I-NOT:     tail __riscv_restore
+;
+; RV64I-LABEL: callee_scs:
+; RV64I-NOT:     call t0, __riscv_save
+; RV64I-NOT:     tail __riscv_restore
+;
+; RV32I-SR-LABEL: callee_scs:
+; RV32I-SR:         call t0, __riscv_save_12
+; RV32I-SR:         tail __riscv_restore_12
+;
+; RV64I-SR-LABEL: callee_scs:
+; RV64I-SR:         call t0, __riscv_save_12
+; RV64I-SR:         tail __riscv_restore_12
+;
+; RV32I-FP-SR-LABEL: callee_scs:
+; RV32I-FP-SR:         call t0, __riscv_save_12
+; RV32I-FP-SR:         tail __riscv_restore_12
+;
+; RV64I-FP-SR-LABEL: callee_scs:
+; RV64I-FP-SR:         call t0, __riscv_save_12
+; RV64I-FP-SR:         tail __riscv_restore_12
+  %val = load [30 x i32], ptr @var2
+  store volatile [30 x i32] %val, ptr @var2
+  ret void
+}
+

diff  --git a/llvm/test/CodeGen/RISCV/shadowcallstack.ll b/llvm/test/CodeGen/RISCV/shadowcallstack.ll
index 4442372637f24..15c09f01c8d4d 100644
--- a/llvm/test/CodeGen/RISCV/shadowcallstack.ll
+++ b/llvm/test/CodeGen/RISCV/shadowcallstack.ll
@@ -1,7 +1,7 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -mtriple=riscv32 -mattr=+reserve-x18 -verify-machineinstrs < %s \
+; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
 ; RUN:   | FileCheck %s --check-prefix=RV32
-; RUN: llc -mtriple=riscv64 -mattr=+reserve-x18 -verify-machineinstrs < %s \
+; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
 ; RUN:   | FileCheck %s --check-prefix=RV64
 
 define void @f1() shadowcallstack {
@@ -34,9 +34,9 @@ declare i32 @bar()
 define i32 @f3() shadowcallstack {
 ; RV32-LABEL: f3:
 ; RV32:       # %bb.0:
-; RV32-NEXT:    sw ra, 0(s2)
-; RV32-NEXT:    addi s2, s2, 4
-; RV32-NEXT:    .cfi_escape 0x16, 0x12, 0x02, 0x82, 0x7c #
+; RV32-NEXT:    sw ra, 0(gp)
+; RV32-NEXT:    addi gp, gp, 4
+; 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
@@ -44,16 +44,16 @@ define i32 @f3() shadowcallstack {
 ; RV32-NEXT:    call bar at plt
 ; RV32-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
 ; RV32-NEXT:    addi sp, sp, 16
-; RV32-NEXT:    lw ra, -4(s2)
-; RV32-NEXT:    addi s2, s2, -4
-; RV32-NEXT:    .cfi_restore s2
+; RV32-NEXT:    lw ra, -4(gp)
+; RV32-NEXT:    addi gp, gp, -4
+; RV32-NEXT:    .cfi_restore gp
 ; RV32-NEXT:    ret
 ;
 ; RV64-LABEL: f3:
 ; RV64:       # %bb.0:
-; RV64-NEXT:    sd ra, 0(s2)
-; RV64-NEXT:    addi s2, s2, 8
-; RV64-NEXT:    .cfi_escape 0x16, 0x12, 0x02, 0x82, 0x78 #
+; RV64-NEXT:    sd ra, 0(gp)
+; RV64-NEXT:    addi gp, gp, 8
+; 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
@@ -61,9 +61,9 @@ define i32 @f3() shadowcallstack {
 ; RV64-NEXT:    call bar at plt
 ; RV64-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
 ; RV64-NEXT:    addi sp, sp, 16
-; RV64-NEXT:    ld ra, -8(s2)
-; RV64-NEXT:    addi s2, s2, -8
-; RV64-NEXT:    .cfi_restore s2
+; RV64-NEXT:    ld ra, -8(gp)
+; RV64-NEXT:    addi gp, gp, -8
+; RV64-NEXT:    .cfi_restore gp
 ; RV64-NEXT:    ret
   %res = call i32 @bar()
   %res1 = add i32 %res, 1
@@ -73,72 +73,72 @@ define i32 @f3() shadowcallstack {
 define i32 @f4() shadowcallstack {
 ; RV32-LABEL: f4:
 ; RV32:       # %bb.0:
-; RV32-NEXT:    sw ra, 0(s2)
-; RV32-NEXT:    addi s2, s2, 4
-; RV32-NEXT:    .cfi_escape 0x16, 0x12, 0x02, 0x82, 0x7c #
+; RV32-NEXT:    sw ra, 0(gp)
+; RV32-NEXT:    addi gp, gp, 4
+; 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 s3, 0(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 s3, -16
+; RV32-NEXT:    .cfi_offset s2, -16
 ; RV32-NEXT:    call bar at plt
 ; RV32-NEXT:    mv s0, a0
 ; RV32-NEXT:    call bar at plt
 ; RV32-NEXT:    mv s1, a0
 ; RV32-NEXT:    call bar at plt
-; RV32-NEXT:    mv s3, a0
+; RV32-NEXT:    mv s2, a0
 ; RV32-NEXT:    call bar at plt
 ; RV32-NEXT:    add s0, s0, s1
-; RV32-NEXT:    add a0, s3, a0
+; 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 s3, 0(sp) # 4-byte Folded Reload
+; RV32-NEXT:    lw s2, 0(sp) # 4-byte Folded Reload
 ; RV32-NEXT:    addi sp, sp, 16
-; RV32-NEXT:    lw ra, -4(s2)
-; RV32-NEXT:    addi s2, s2, -4
-; RV32-NEXT:    .cfi_restore s2
+; RV32-NEXT:    lw ra, -4(gp)
+; RV32-NEXT:    addi gp, gp, -4
+; RV32-NEXT:    .cfi_restore gp
 ; RV32-NEXT:    ret
 ;
 ; RV64-LABEL: f4:
 ; RV64:       # %bb.0:
-; RV64-NEXT:    sd ra, 0(s2)
-; RV64-NEXT:    addi s2, s2, 8
-; RV64-NEXT:    .cfi_escape 0x16, 0x12, 0x02, 0x82, 0x78 #
+; RV64-NEXT:    sd ra, 0(gp)
+; RV64-NEXT:    addi gp, gp, 8
+; 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 s3, 0(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 s3, -32
+; RV64-NEXT:    .cfi_offset s2, -32
 ; RV64-NEXT:    call bar at plt
 ; RV64-NEXT:    mv s0, a0
 ; RV64-NEXT:    call bar at plt
 ; RV64-NEXT:    mv s1, a0
 ; RV64-NEXT:    call bar at plt
-; RV64-NEXT:    mv s3, a0
+; RV64-NEXT:    mv s2, a0
 ; RV64-NEXT:    call bar at plt
 ; RV64-NEXT:    add s0, s0, s1
-; RV64-NEXT:    add a0, s3, a0
+; 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 s3, 0(sp) # 8-byte Folded Reload
+; RV64-NEXT:    ld s2, 0(sp) # 8-byte Folded Reload
 ; RV64-NEXT:    addi sp, sp, 32
-; RV64-NEXT:    ld ra, -8(s2)
-; RV64-NEXT:    addi s2, s2, -8
-; RV64-NEXT:    .cfi_restore s2
+; RV64-NEXT:    ld ra, -8(gp)
+; RV64-NEXT:    addi gp, gp, -8
+; RV64-NEXT:    .cfi_restore gp
 ; RV64-NEXT:    ret
   %res1 = call i32 @bar()
   %res2 = call i32 @bar()
@@ -153,28 +153,28 @@ define i32 @f4() shadowcallstack {
 define i32 @f5() shadowcallstack nounwind {
 ; RV32-LABEL: f5:
 ; RV32:       # %bb.0:
-; RV32-NEXT:    sw ra, 0(s2)
-; RV32-NEXT:    addi s2, s2, 4
+; RV32-NEXT:    sw ra, 0(gp)
+; RV32-NEXT:    addi gp, gp, 4
 ; RV32-NEXT:    addi sp, sp, -16
 ; RV32-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
 ; RV32-NEXT:    call bar at plt
 ; RV32-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
 ; RV32-NEXT:    addi sp, sp, 16
-; RV32-NEXT:    lw ra, -4(s2)
-; RV32-NEXT:    addi s2, s2, -4
+; RV32-NEXT:    lw ra, -4(gp)
+; RV32-NEXT:    addi gp, gp, -4
 ; RV32-NEXT:    ret
 ;
 ; RV64-LABEL: f5:
 ; RV64:       # %bb.0:
-; RV64-NEXT:    sd ra, 0(s2)
-; RV64-NEXT:    addi s2, s2, 8
+; RV64-NEXT:    sd ra, 0(gp)
+; RV64-NEXT:    addi gp, gp, 8
 ; RV64-NEXT:    addi sp, sp, -16
 ; RV64-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
 ; RV64-NEXT:    call bar at plt
 ; RV64-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
 ; RV64-NEXT:    addi sp, sp, 16
-; RV64-NEXT:    ld ra, -8(s2)
-; RV64-NEXT:    addi s2, s2, -8
+; RV64-NEXT:    ld ra, -8(gp)
+; RV64-NEXT:    addi gp, gp, -8
 ; RV64-NEXT:    ret
   %res = call i32 @bar()
   %res1 = add i32 %res, 1


        


More information about the cfe-commits mailing list