[vm, compiler] Support ShadowCallStack on Fuchsia RISC-V.

Remove fixed uses of X18.

TEST=ci (Linux), speculative (Fuchsia)
Change-Id: I20e31fc2ab7d44cbf02e591be92261067158509d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/244943
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
Ryan Macnak 2022-05-16 22:35:55 +00:00 committed by Commit Bot
parent e1773c7ebc
commit 09b7f36b2f
4 changed files with 42 additions and 22 deletions

View file

@ -3031,9 +3031,9 @@ void Assembler::StoreBarrier(Register object,
if (object != kWriteBarrierValueReg) {
PushRegister(kWriteBarrierValueReg);
} else {
COMPILE_ASSERT(S2 != kWriteBarrierValueReg);
COMPILE_ASSERT(S3 != kWriteBarrierValueReg);
objectForCall = (value == S2) ? S3 : S2;
COMPILE_ASSERT(S4 != kWriteBarrierValueReg);
objectForCall = (value == S3) ? S4 : S3;
PushRegisterPair(kWriteBarrierValueReg, objectForCall);
mv(objectForCall, object);
}

View file

@ -272,12 +272,12 @@ void StubCodeCompiler::GenerateExitSafepointIgnoreUnwindInProgressStub(
// Stack: set up for native call (SP), aligned, CSP < SP
//
// On exit:
// S2: clobbered, although normally callee-saved
// S3: clobbered, although normally callee-saved
// Stack: preserved, CSP == SP
void StubCodeCompiler::GenerateCallNativeThroughSafepointStub(
Assembler* assembler) {
COMPILE_ASSERT(IsAbiPreservedRegister(S2));
__ mv(S2, RA);
COMPILE_ASSERT(IsAbiPreservedRegister(S3));
__ mv(S3, RA);
__ LoadImmediate(T1, target::Thread::exit_through_ffi());
__ TransitionGeneratedToNative(T0, FPREG, T1 /*volatile*/,
/*enter_safepoint=*/true);
@ -294,7 +294,7 @@ void StubCodeCompiler::GenerateCallNativeThroughSafepointStub(
__ jalr(T0);
__ TransitionNativeToGenerated(T1, /*leave_safepoint=*/true);
__ jr(S2);
__ jr(S3);
}
#if !defined(DART_PRECOMPILER)
@ -1321,7 +1321,9 @@ void StubCodeCompiler::GenerateInvokeDartCodeStub(Assembler* assembler) {
__ lx(TMP2, Address(A3, target::Thread::invoke_dart_code_stub_offset()));
__ PushRegister(TMP2);
#if defined(USING_SHADOW_CALL_STACK)
#if defined(DART_TARGET_OS_FUCHSIA)
__ sx(S2, Address(A3, target::Thread::saved_shadow_call_stack_offset()));
#elif defined(USING_SHADOW_CALL_STACK)
#error Unimplemented
#endif
@ -3032,7 +3034,9 @@ void StubCodeCompiler::GenerateJumpToFrameStub(Assembler* assembler) {
__ mv(SP, A1); // Stack pointer.
__ mv(FP, A2); // Frame_pointer.
__ mv(THR, A3);
#if defined(USING_SHADOW_CALL_STACK)
#if defined(DART_TARGET_OS_FUCHSIA)
__ lx(S2, Address(THR, target::Thread::saved_shadow_call_stack_offset()));
#elif defined(USING_SHADOW_CALL_STACK)
#error Unimplemented
#endif
Label exit_through_non_ffi;

View file

@ -61,7 +61,7 @@ enum Register {
A5 = 15, // PP, untagged
A6 = 16,
A7 = 17,
S2 = 18,
S2 = 18, // ShadowCallStack
S3 = 19,
S4 = 20, // ARGS_DESC_REG
S5 = 21, // IC_DATA_REG
@ -192,10 +192,10 @@ struct InstantiationABI {
// 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 = S2;
static constexpr Register kScratchReg = S3;
static constexpr Register kSubTypeArgumentReg = S4;
static constexpr Register kSuperTypeArgumentReg = S5;
static constexpr Register kInstanceTypeArgumentsReg = S3;
static constexpr Register kScratchReg = S4;
static constexpr Register kSubTypeArgumentReg = S5;
static constexpr Register kSuperTypeArgumentReg = S6;
// Must be pushed/popped whenever generic type arguments are being checked as
// they overlap with registers in TypeTestABI.
@ -210,10 +210,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 = S2;
static constexpr Register kInstanceInstantiatorTypeArgumentsReg = S3;
static constexpr Register kInstanceParentFunctionTypeArgumentsReg = S4;
static constexpr Register kInstanceDelayedFunctionTypeArgumentsReg = S5;
static constexpr Register kInstanceCidOrSignatureReg = S3;
static constexpr Register kInstanceInstantiatorTypeArgumentsReg = S4;
static constexpr Register kInstanceParentFunctionTypeArgumentsReg = S5;
static constexpr Register kInstanceDelayedFunctionTypeArgumentsReg = S6;
static const intptr_t kInternalRegisters =
(1 << kInstanceCidOrSignatureReg) |
@ -443,15 +443,30 @@ constexpr RegList kAbiPreservedCpuRegs = R(S1) | R(S2) | R(S3) | R(S4) | R(S5) |
R(S6) | R(S7) | R(S8) | R(S9) |
R(S10) | R(S11);
constexpr int kAbiPreservedCpuRegCount = 11;
#if defined(DART_TARGET_OS_FUCHSIA)
// We rely on X18 not being touched by Dart generated assembly or stubs at all.
// We rely on that any calls into C++ also preserve X18.
constexpr intptr_t kReservedCpuRegisters =
R(ZR) | R(TP) | R(GP) | R(SP) | R(FP) | R(TMP) | R(TMP2) | R(PP) | R(THR) |
R(RA) | R(WRITE_BARRIER_MASK) | R(NULL_REG) | R(DISPATCH_TABLE_REG) |
R(FAR_TMP) | R(18);
constexpr intptr_t kNumberOfReservedCpuRegisters = 15;
#else
constexpr intptr_t kReservedCpuRegisters =
R(ZR) | R(TP) | R(GP) | R(SP) | R(FP) | R(TMP) | R(TMP2) | R(PP) | R(THR) |
R(RA) | R(WRITE_BARRIER_MASK) | R(NULL_REG) | R(DISPATCH_TABLE_REG) |
R(FAR_TMP);
constexpr intptr_t kNumberOfReservedCpuRegisters = 14;
#endif
// CPU registers available to Dart allocator.
constexpr RegList kDartAvailableCpuRegs =
kAllCpuRegistersList & ~kReservedCpuRegisters;
#if defined(DART_TARGET_OS_FUCHSIA)
constexpr int kNumberOfDartAvailableCpuRegs = 17;
#else
constexpr int kNumberOfDartAvailableCpuRegs = 18;
#endif
// Registers X8-15 (S0-1,A0-5) have more compressed instructions available.
constexpr int kRegisterAllocationBias = 8;
// Registers available to Dart that are not preserved by runtime calls.
@ -511,7 +526,8 @@ class CallingConventions {
static constexpr Register kSecondReturnReg = A1;
static constexpr FpuRegister kReturnFpuReg = FA0;
static constexpr Register kFfiAnyNonAbiRegister = S2; // S0=FP, S1=THR
// S0=FP, S1=THR, S2=ShadowCallStack
static constexpr Register kFfiAnyNonAbiRegister = S3;
static constexpr Register kFirstNonArgumentRegister = T0;
static constexpr Register kSecondNonArgumentRegister = T1;
static constexpr Register kStackPointerRegister = SPREG;

View file

@ -418,16 +418,16 @@ bool PcRelativeTrampolineJumpPattern::IsValid() const {
intptr_t TypeTestingStubCallPattern::GetSubtypeTestCachePoolIndex() {
// Calls to the type testing stubs look like:
// lx s3, ...
// lx s4, ...
// lx Rn, idx(pp)
// jalr s3
// jalr s4
// 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) == 0x9982) { // jalr s3
if (*reinterpret_cast<uint16_t*>(pc_ - 2) == 0x9a02) { // jalr s4
// indirect call
// xxxx c.jalr s3
// xxxx c.jalr s4
Register reg;
intptr_t pool_index = -1;
InstructionPattern::DecodeLoadWordFromPool(pc_ - 2, &reg, &pool_index);