[vm, compiler] Update the RISC-V shadow call stack pointer from S2 to GP.

Cf. https://reviews.llvm.org/D146463

TEST=ci (Linux), inspect disassembly (Fuchsia/Android)
Change-Id: I3ef4bc4c3212e80221ec7edaebfa33e9eb1db03d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/291660
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
This commit is contained in:
Ryan Macnak
2023-04-13 19:29:47 +00:00
committed by Commit Queue
parent f70238a83b
commit 867dfd226e
8 changed files with 279 additions and 267 deletions
File diff suppressed because it is too large Load Diff
@@ -3228,6 +3228,10 @@ void StubCodeCompiler::GenerateJumpToFrameStub() {
__ mov(THR, R3);
__ SetupCSPFromThread(THR);
#if defined(DART_TARGET_OS_FUCHSIA)
// We need to restore the shadow call stack pointer like longjmp would,
// effectively popping all the return addresses between the Dart exit frame
// and Exceptions::JumpToFrame, otherwise the shadow call stack might
// eventually overflow.
__ ldr(R18, Address(THR, target::Thread::saved_shadow_call_stack_offset()));
#elif defined(USING_SHADOW_CALL_STACK)
#error Unimplemented
@@ -1317,8 +1317,8 @@ void StubCodeCompiler::GenerateInvokeDartCodeStub() {
__ lx(TMP2, Address(A3, target::Thread::invoke_dart_code_stub_offset()));
__ sx(TMP2, Address(SP, 0 * target::kWordSize));
#if defined(DART_TARGET_OS_FUCHSIA)
__ sx(S2, Address(A3, target::Thread::saved_shadow_call_stack_offset()));
#if defined(DART_TARGET_OS_FUCHSIA) || defined(DART_TARGET_OS_ANDROID)
__ sx(GP, Address(A3, target::Thread::saved_shadow_call_stack_offset()));
#elif defined(USING_SHADOW_CALL_STACK)
#error Unimplemented
#endif
@@ -3002,8 +3002,12 @@ void StubCodeCompiler::GenerateJumpToFrameStub() {
__ mv(SP, A1); // Stack pointer.
__ mv(FP, A2); // Frame_pointer.
__ mv(THR, A3);
#if defined(DART_TARGET_OS_FUCHSIA)
__ lx(S2, Address(THR, target::Thread::saved_shadow_call_stack_offset()));
#if defined(DART_TARGET_OS_FUCHSIA) || defined(DART_TARGET_OS_ANDROID)
// We need to restore the shadow call stack pointer like longjmp would,
// effectively popping all the return addresses between the Dart exit frame
// and Exceptions::JumpToFrame, otherwise the shadow call stack might
// eventually overflow.
__ lx(GP, Address(THR, target::Thread::saved_shadow_call_stack_offset()));
#elif defined(USING_SHADOW_CALL_STACK)
#error Unimplemented
#endif
+17 -20
View File
@@ -46,7 +46,7 @@ enum Register {
ZR = 0,
RA = 1,
SP = 2,
GP = 3,
GP = 3, // Shadow call stack on Fuchsia and Android
TP = 4,
T0 = 5,
T1 = 6,
@@ -61,7 +61,7 @@ enum Register {
A5 = 15, // PP, untagged
A6 = 16,
A7 = 17,
S2 = 18, // ShadowCallStack
S2 = 18,
S3 = 19,
S4 = 20, // ARGS_DESC_REG
S5 = 21, // IC_DATA_REG
@@ -198,19 +198,19 @@ struct InstantiateTAVInternalRegs {
static constexpr intptr_t kSavedRegisters = 0;
// Additional registers used to probe hash-based caches.
static constexpr Register kEntryStartReg = S3;
static constexpr Register kProbeMaskReg = S4;
static constexpr Register kProbeDistanceReg = S5;
static constexpr Register kCurrentEntryIndexReg = S6;
static constexpr Register kEntryStartReg = S2;
static constexpr Register kProbeMaskReg = S3;
static constexpr Register kProbeDistanceReg = S4;
static constexpr Register kCurrentEntryIndexReg = S5;
};
// Registers in addition to those listed in TypeTestABI used inside the
// implementation of type testing stubs that are _not_ preserved.
struct TTSInternalRegs {
static constexpr Register kInstanceTypeArgumentsReg = S3;
static constexpr Register kScratchReg = S4;
static constexpr Register kSubTypeArgumentReg = S5;
static constexpr Register kSuperTypeArgumentReg = S6;
static constexpr Register kInstanceTypeArgumentsReg = S2;
static constexpr Register kScratchReg = S3;
static constexpr Register kSubTypeArgumentReg = S4;
static constexpr Register kSuperTypeArgumentReg = S5;
// Must be pushed/popped whenever generic type arguments are being checked as
// they overlap with registers in TypeTestABI.
@@ -225,10 +225,10 @@ struct TTSInternalRegs {
// Registers in addition to those listed in TypeTestABI used inside the
// implementation of subtype test cache stubs that are _not_ preserved.
struct STCInternalRegs {
static constexpr Register kInstanceCidOrSignatureReg = S3;
static constexpr Register kInstanceInstantiatorTypeArgumentsReg = S4;
static constexpr Register kInstanceParentFunctionTypeArgumentsReg = S5;
static constexpr Register kInstanceDelayedFunctionTypeArgumentsReg = S6;
static constexpr Register kInstanceCidOrSignatureReg = S2;
static constexpr Register kInstanceInstantiatorTypeArgumentsReg = S3;
static constexpr Register kInstanceParentFunctionTypeArgumentsReg = S4;
static constexpr Register kInstanceDelayedFunctionTypeArgumentsReg = S5;
static constexpr intptr_t kInternalRegisters =
(1 << kInstanceCidOrSignatureReg) |
@@ -493,13 +493,10 @@ constexpr RegList kAbiPreservedCpuRegs = R(S1) | R(S2) | R(S3) | R(S4) | R(S5) |
R(S10) | R(S11);
constexpr int kAbiPreservedCpuRegCount = 11;
// S2 is reserved as the shadow call stack pointer on Fuchsia and Android.
// Although it is available on Linux, we mark it as reserved unconditionally to
// avoid adding another dimenision for OS into the extracted runtime offsets.
constexpr RegList kReservedCpuRegisters =
R(ZR) | R(TP) | R(GP) | R(SP) | R(FP) | R(TMP) | R(TMP2) | R(PP) | R(THR) |
R(RA) | R(WRITE_BARRIER_STATE) | R(NULL_REG) | R(DISPATCH_TABLE_REG) |
R(FAR_TMP) | R(S2);
R(FAR_TMP);
constexpr intptr_t kNumberOfReservedCpuRegisters =
Utils::CountOneBits32(kReservedCpuRegisters);
// CPU registers available to Dart allocator.
@@ -568,8 +565,8 @@ class CallingConventions {
static constexpr Register kSecondReturnReg = A1;
static constexpr FpuRegister kReturnFpuReg = FA0;
// S0=FP, S1=THR, S2=ShadowCallStack
static constexpr Register kFfiAnyNonAbiRegister = S3;
// S0=FP, S1=THR
static constexpr Register kFfiAnyNonAbiRegister = S2;
static constexpr Register kFirstNonArgumentRegister = T0;
static constexpr Register kSecondNonArgumentRegister = T1;
static constexpr Register kStackPointerRegister = SPREG;
+3 -3
View File
@@ -414,10 +414,10 @@ intptr_t TypeTestingStubCallPattern::GetSubtypeTestCachePoolIndex() {
// where Rn = TypeTestABI::kSubtypeTestCacheReg.
// Ensure the caller of the type testing stub (whose return address is [pc_])
// branched via `blr R9` or a pc-relative call.
if (*reinterpret_cast<uint16_t*>(pc_ - 2) == 0x9a02) { // jalr s4
// branched via `jalr s3` or a pc-relative call.
if (*reinterpret_cast<uint16_t*>(pc_ - 2) == 0x9982) { // jalr s3
// indirect call
// xxxx c.jalr s4
// xxxx c.jalr s3
Register reg;
intptr_t pool_index = -1;
InstructionPattern::DecodeLoadWordFromPool(pc_ - 2, &reg, &pool_index);
+3
View File
@@ -3890,6 +3890,9 @@ void Simulator::JumpToFrame(uword pc, uword sp, uword fp, Thread* thread) {
set_register(nullptr, FP, static_cast<int64_t>(fp));
set_register(nullptr, THR, reinterpret_cast<int64_t>(thread));
set_register(nullptr, R31, thread->saved_stack_limit() - 4096);
#if defined(DART_TARGET_OS_FUCHSIA)
set_register(nullptr, R18, thread->saved_shadow_call_stack());
#endif
// Set the tag.
thread->set_vm_tag(VMTag::kDartTagId);
// Clear top exit frame.
+3
View File
@@ -449,6 +449,9 @@ void Simulator::JumpToFrame(uword pc, uword sp, uword fp, Thread* thread) {
set_xreg(SP, static_cast<uintx_t>(sp));
set_xreg(FP, static_cast<uintx_t>(fp));
set_xreg(THR, reinterpret_cast<uintx_t>(thread));
#if defined(DART_TARGET_OS_FUCHSIA) || defined(DART_TARGET_OS_ANDROID)
set_xreg(GP, thread->saved_shadow_call_stack());
#endif
// Set the tag.
thread->set_vm_tag(VMTag::kDartTagId);
// Clear top exit frame.
+1
View File
@@ -403,6 +403,7 @@ class Thread : public ThreadState {
saved_safestack_limit_ = limit;
}
#endif
uword saved_shadow_call_stack() const { return saved_shadow_call_stack_; }
static uword saved_shadow_call_stack_offset() {
return OFFSET_OF(Thread, saved_shadow_call_stack_);
}