diff --git a/runtime/vm/compiler/assembler/assembler_riscv.cc b/runtime/vm/compiler/assembler/assembler_riscv.cc index 668c0198011..094182f7985 100644 --- a/runtime/vm/compiler/assembler/assembler_riscv.cc +++ b/runtime/vm/compiler/assembler/assembler_riscv.cc @@ -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); } diff --git a/runtime/vm/compiler/stub_code_compiler_riscv.cc b/runtime/vm/compiler/stub_code_compiler_riscv.cc index b9fc91d8675..db657921275 100644 --- a/runtime/vm/compiler/stub_code_compiler_riscv.cc +++ b/runtime/vm/compiler/stub_code_compiler_riscv.cc @@ -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; diff --git a/runtime/vm/constants_riscv.h b/runtime/vm/constants_riscv.h index 91e9d7872bf..435c5f80de2 100644 --- a/runtime/vm/constants_riscv.h +++ b/runtime/vm/constants_riscv.h @@ -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; diff --git a/runtime/vm/instructions_riscv.cc b/runtime/vm/instructions_riscv.cc index 3a7d2a86508..e753c2fd6c3 100644 --- a/runtime/vm/instructions_riscv.cc +++ b/runtime/vm/instructions_riscv.cc @@ -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(pc_ - 2) == 0x9982) { // jalr s3 + if (*reinterpret_cast(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, ®, &pool_index);