From d87cfc5fd57efdc2f4498c0aa6200dd0a8c4557f Mon Sep 17 00:00:00 2001 From: Dong-Heon Jung Date: Wed, 3 Jan 2024 19:34:00 +0900 Subject: [PATCH 01/22] [RISC-V] Fix crossgen2 --- src/coreclr/jit/emitriscv64.cpp | 2 +- src/coreclr/pal/inc/rt/ntimage.h | 1 - .../Common/Compiler/DependencyAnalysis/ObjectDataBuilder.cs | 1 - src/coreclr/tools/Common/Compiler/InstructionSetSupport.cs | 4 ++++ .../tools/Common/Compiler/VectorFieldLayoutAlgorithm.cs | 4 ++-- src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs | 3 +++ 6 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index fac65fda89897..179d0d8b0e9ec 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -1546,7 +1546,7 @@ unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t #endif emitOutput_Instr(dst, 0x00000067 | (REG_DEFAULT_HELPER_CALL_TARGET << 15) | reg2 << 7); - emitRecordRelocation(dst - 4, (BYTE*)addr, IMAGE_REL_RISCV64_JALR); + emitRecordRelocation(dst - 4, (BYTE*)addr, IMAGE_REL_RISCV64_PC); } else { diff --git a/src/coreclr/pal/inc/rt/ntimage.h b/src/coreclr/pal/inc/rt/ntimage.h index 17680e2a3e9f1..3c7de05234049 100644 --- a/src/coreclr/pal/inc/rt/ntimage.h +++ b/src/coreclr/pal/inc/rt/ntimage.h @@ -1025,7 +1025,6 @@ typedef IMAGE_RELOCATION UNALIGNED *PIMAGE_RELOCATION; // RISCV64 relocation types // #define IMAGE_REL_RISCV64_PC 0x0003 -#define IMAGE_REL_RISCV64_JALR 0x0004 // // CEF relocation types. diff --git a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ObjectDataBuilder.cs b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ObjectDataBuilder.cs index 1181b642a7df7..b5128ff27fb1f 100644 --- a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ObjectDataBuilder.cs +++ b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ObjectDataBuilder.cs @@ -321,7 +321,6 @@ public void EmitReloc(ISymbolNode symbol, RelocType relocType, int delta = 0) case RelocType.IMAGE_REL_BASED_LOONGARCH64_PC: case RelocType.IMAGE_REL_BASED_LOONGARCH64_JIR: - //TODO: consider removal of IMAGE_REL_RISCV64_JALR from runtime too case RelocType.IMAGE_REL_BASED_RISCV64_PC: Debug.Assert(delta == 0); // Do not vacate space for this kind of relocation, because diff --git a/src/coreclr/tools/Common/Compiler/InstructionSetSupport.cs b/src/coreclr/tools/Common/Compiler/InstructionSetSupport.cs index bb74b7085d3cc..1e7a392eca49e 100644 --- a/src/coreclr/tools/Common/Compiler/InstructionSetSupport.cs +++ b/src/coreclr/tools/Common/Compiler/InstructionSetSupport.cs @@ -89,6 +89,10 @@ public static string GetHardwareIntrinsicId(TargetArchitecture architecture, Typ if (potentialType.Namespace != "System.Runtime.Intrinsics.Arm") return ""; } + else if (architecture == TargetArchitecture.RiscV64) + { + return ""; + } else { throw new InternalCompilerErrorException("Unknown architecture"); diff --git a/src/coreclr/tools/Common/Compiler/VectorFieldLayoutAlgorithm.cs b/src/coreclr/tools/Common/Compiler/VectorFieldLayoutAlgorithm.cs index ac5247190775a..33d894f75893e 100644 --- a/src/coreclr/tools/Common/Compiler/VectorFieldLayoutAlgorithm.cs +++ b/src/coreclr/tools/Common/Compiler/VectorFieldLayoutAlgorithm.cs @@ -52,7 +52,7 @@ public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType defTyp // to the same alignment as __m128, which is supported by the ABI. alignment = new LayoutInt(8); } - else if (defType.Context.Target.Architecture == TargetArchitecture.ARM64) + else if (defType.Context.Target.Architecture == TargetArchitecture.ARM64 || defType.Context.Target.Architecture == TargetArchitecture.RiscV64) { // The Procedure Call Standard for ARM 64-bit (with SVE support) defaults to // 16-byte alignment for __m256. @@ -73,7 +73,7 @@ public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType defTyp // to the same alignment as __m128, which is supported by the ABI. alignment = new LayoutInt(8); } - else if (defType.Context.Target.Architecture == TargetArchitecture.ARM64) + else if (defType.Context.Target.Architecture == TargetArchitecture.ARM64 || defType.Context.Target.Architecture == TargetArchitecture.RiscV64) { // The Procedure Call Standard for ARM 64-bit (with SVE support) defaults to // 16-byte alignment for __m256. diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index cadc58a701451..d53f8916a59b0 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -4084,6 +4084,9 @@ private uint getJitFlags(ref CORJIT_FLAGS flags, uint sizeInBytes) if (targetArchitecture == TargetArchitecture.ARM && !_compilation.TypeSystemContext.Target.IsWindows) flags.Set(CorJitFlag.CORJIT_FLAG_RELATIVE_CODE_RELOCS); + if (targetArchitecture == TargetArchitecture.RiscV64) + flags.Set(CorJitFlag.CORJIT_FLAG_FRAMED); + if (this.MethodBeingCompiled.IsUnmanagedCallersOnly) { // Validate UnmanagedCallersOnlyAttribute usage From 6fc0d21d54864fce1c889f7f802ac1d36d6767a5 Mon Sep 17 00:00:00 2001 From: Dong-Heon Jung Date: Thu, 4 Jan 2024 16:30:31 +0900 Subject: [PATCH 02/22] [RISC-V] Fix typo in codegen --- src/coreclr/jit/codegenriscv64.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/jit/codegenriscv64.cpp b/src/coreclr/jit/codegenriscv64.cpp index 05f7a2c11f443..25054ee0e744e 100644 --- a/src/coreclr/jit/codegenriscv64.cpp +++ b/src/coreclr/jit/codegenriscv64.cpp @@ -5169,7 +5169,7 @@ void CodeGen::genSetGSSecurityCookie(regNumber initReg, bool* pInitRegZeroed) { if (compiler->opts.compReloc) { - emit->emitIns_R_AI(INS_jalr, EA_PTR_DSP_RELOC, initReg, (ssize_t)compiler->gsGlobalSecurityCookieAddr); + emit->emitIns_R_AI(INS_jal, EA_PTR_DSP_RELOC, initReg, (ssize_t)compiler->gsGlobalSecurityCookieAddr); } else { From 23fee529d47f967542f9e618d584159c48737ec3 Mon Sep 17 00:00:00 2001 From: Dong-Heon Jung Date: Thu, 4 Jan 2024 17:26:49 +0900 Subject: [PATCH 03/22] [RISC-V] Update assert to support all rel insts --- .../Compiler/DependencyAnalysis/Relocation.cs | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/Relocation.cs b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/Relocation.cs index 337811103e35f..5748e7b07915b 100644 --- a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/Relocation.cs +++ b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/Relocation.cs @@ -420,9 +420,11 @@ private static unsafe int GetRiscV64PC(uint* pCode) // first get the high 20 bits, int imm = (int)((auipcInstr & 0xfffff000)); // then get the low 12 bits, - uint addiInstr = *(pCode + 1); - Debug.Assert((addiInstr & 0x707f) == 0x00000013); - imm += ((int)(addiInstr)) >> 20; + uint nextInstr = *(pCode + 1); + Debug.Assert((nextInstr & 0x707f) == 0x00000013 || + (nextInstr & 0x707f) == 0x00000067 || + (nextInstr & 0x707f) == 0x00003003); + imm += ((int)(nextInstr)) >> 20; return imm; } @@ -434,6 +436,10 @@ private static unsafe int GetRiscV64PC(uint* pCode) // case:EA_PTR_DSP_RELOC // auipc reg, off-hi-20bits // ld reg, reg, off-lo-12bits + // case: + // INS_OPTS_C + // auipc reg, off-hi-20bits + // jalr reg, reg, off-lo-12bits private static unsafe void PutRiscV64PC(uint* pCode, long imm32) { // Verify that we got a valid offset @@ -446,10 +452,12 @@ private static unsafe void PutRiscV64PC(uint* pCode, long imm32) auipcInstr |= (uint)((imm32 + 0x800) & 0xfffff000); *pCode = auipcInstr; - uint addiInstr = *(pCode + 1); - Debug.Assert((addiInstr & 0x707f) == 0x00000013); - addiInstr |= (uint)((doff & 0xfff) << 20); - *(pCode + 1) = addiInstr; + uint nextInstr = *(pCode + 1); + Debug.Assert((nextInstr & 0x707f) == 0x00000013 || + (nextInstr & 0x707f) == 0x00000067 || + (nextInstr & 0x707f) == 0x00003003); + nextInstr |= (uint)((doff & 0xfff) << 20); + *(pCode + 1) = nextInstr; Debug.Assert(GetRiscV64PC(pCode) == imm32); } From 464c17015b65bcd2abadbb6e7b71dd718642d363 Mon Sep 17 00:00:00 2001 From: Dong-Heon Jung Date: Wed, 10 Jan 2024 10:41:23 +0900 Subject: [PATCH 04/22] [RISC-V] Fix helper function call --- src/coreclr/jit/gentree.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index ef4dd9be14691..ae3ccc806c4b5 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -5570,7 +5570,7 @@ struct GenTreeCall final : public GenTree return WellKnownArg::VirtualStubCell; } -#if defined(TARGET_ARMARCH) +#if defined(TARGET_ARMARCH) || defined(TARGET_RISCV64) // For ARM architectures, we always use an indirection cell for R2R calls. if (IsR2RRelativeIndir() && !IsDelegateInvoke()) { From 56a39cc0b364b32e0250947d93bb26eb4566c5d1 Mon Sep 17 00:00:00 2001 From: Dong-Heon Jung Date: Thu, 11 Jan 2024 16:43:37 +0900 Subject: [PATCH 05/22] [RISC-V] Update GetRISCV64PassStructInRegisterFlags --- .../RISCV64PassStructInRegister.cs | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/coreclr/tools/Common/JitInterface/RISCV64PassStructInRegister.cs b/src/coreclr/tools/Common/JitInterface/RISCV64PassStructInRegister.cs index 19ffe401a0212..d6c820b8f904c 100644 --- a/src/coreclr/tools/Common/JitInterface/RISCV64PassStructInRegister.cs +++ b/src/coreclr/tools/Common/JitInterface/RISCV64PassStructInRegister.cs @@ -29,12 +29,6 @@ public static uint GetRISCV64PassStructInRegisterFlags(TypeDesc typeDesc) return (uint)StructFloatFieldInfoFlags.STRUCT_NO_FLOAT_FIELD; } - //// The SIMD Intrinsic types are meant to be handled specially and should not be passed as struct registers - if (typeDesc.IsIntrinsic) - { - throw new NotImplementedException("For RISCV64, SIMD would be implemented later"); - } - MetadataType mdType = typeDesc as MetadataType; Debug.Assert(mdType != null); @@ -85,6 +79,16 @@ public static uint GetRISCV64PassStructInRegisterFlags(TypeDesc typeDesc) { floatFieldFlags |= (uint)StructFloatFieldInfoFlags.STRUCT_SECOND_FIELD_DOUBLE; } + + // Pass with two integer registers in `struct {int a, int b, float/double c}` cases + if (fieldIndex == 1 && + (floatFieldFlags | + (uint)StructFloatFieldInfoFlags.STRUCT_FIRST_FIELD_SIZE_IS8 | + (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_SECOND) == + floatFieldFlags) + { + floatFieldFlags = (uint)StructFloatFieldInfoFlags.STRUCT_NO_FLOAT_FIELD; + } } break; @@ -106,6 +110,16 @@ public static uint GetRISCV64PassStructInRegisterFlags(TypeDesc typeDesc) { floatFieldFlags |= (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_SECOND; } + + // Pass with two integer registers in `struct {int a, int b, float/double c}` cases + if (fieldIndex == 1 && + (floatFieldFlags | + (uint)StructFloatFieldInfoFlags.STRUCT_FIRST_FIELD_SIZE_IS8 | + (uint)StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_SECOND) == + floatFieldFlags) + { + floatFieldFlags = (uint)StructFloatFieldInfoFlags.STRUCT_NO_FLOAT_FIELD; + } } break; From 381858cb2335782d66e8a6439db9c6f053adff21 Mon Sep 17 00:00:00 2001 From: Dong-Heon Jung Date: Fri, 12 Jan 2024 11:14:27 +0900 Subject: [PATCH 06/22] [RISC-V] Fix int arg reg passing for float type A failure during crossgen2 SPC.dll `System.Diagnostics.Tracing.NativeRuntimeEventSource:LogThreadPoolWorkerThreadAdjustmentStats(double,double,double,double,double,double,double,double,double,ushort,ushort)` --- src/coreclr/jit/codegenlinear.cpp | 17 ++++++++++++----- src/coreclr/jit/lsra.cpp | 6 ++++++ src/coreclr/jit/regset.cpp | 16 +++++++++++++--- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/src/coreclr/jit/codegenlinear.cpp b/src/coreclr/jit/codegenlinear.cpp index 67f4bb73c0eb1..b41b24f2a3a5c 100644 --- a/src/coreclr/jit/codegenlinear.cpp +++ b/src/coreclr/jit/codegenlinear.cpp @@ -1258,7 +1258,7 @@ void CodeGen::genUnspillRegIfNeeded(GenTree* tree) unspillType = lcl->TypeGet(); } -#if defined(TARGET_LOONGARCH64) +#if defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) if (varTypeIsFloating(unspillType) && emitter::isGeneralRegister(tree->GetRegNum())) { unspillType = unspillType == TYP_FLOAT ? TYP_INT : TYP_LONG; @@ -1310,15 +1310,22 @@ void CodeGen::genUnspillRegIfNeeded(GenTree* tree) // The spill temp allocated for it is associated with the original tree that defined the // register that it was spilled from. // So we use 'unspillTree' to recover that spill temp. - TempDsc* t = regSet.rsUnspillInPlace(unspillTree, unspillTree->GetRegNum()); - emitAttr emitType = emitActualTypeSize(unspillTree->TypeGet()); + TempDsc* t = regSet.rsUnspillInPlace(unspillTree, unspillTree->GetRegNum()); + var_types unspillType = unspillTree->TypeGet(); + // Reload into the register specified by 'tree' which may be a GT_RELOAD. regNumber dstReg = tree->GetRegNum(); - GetEmitter()->emitIns_R_S(ins_Load(unspillTree->gtType), emitType, dstReg, t->tdTempNum(), 0); +#ifdef TARGET_RISCV64 + if (varTypeIsFloating(unspillType) && emitter::isGeneralRegister(dstReg)) + { + unspillType = (unspillType == TYP_FLOAT) ? TYP_INT : TYP_LONG; + } +#endif // TARGET_RISCV64 + GetEmitter()->emitIns_R_S(ins_Load(unspillType), emitActualTypeSize(unspillType), dstReg, t->tdTempNum(), 0); regSet.tmpRlsTemp(t); unspillTree->gtFlags &= ~GTF_SPILLED; - gcInfo.gcMarkRegPtrVal(dstReg, unspillTree->TypeGet()); + gcInfo.gcMarkRegPtrVal(dstReg, unspillType); } } } diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp index 37d85e23b9150..caecef1b795db 100644 --- a/src/coreclr/jit/lsra.cpp +++ b/src/coreclr/jit/lsra.cpp @@ -7045,6 +7045,12 @@ void LinearScan::updateMaxSpill(RefPosition* refPosition) if (!treeNode->IsMultiRegNode()) { type = getDefType(treeNode); +#ifdef TARGET_RISCV64 + if (isFloatRegType(type) && genIsValidIntReg(treeNode->GetRegNum())) + { + type = (type == TYP_FLOAT) ? TYP_INT : TYP_LONG; + } +#endif // TARGET_RISCV64 } else { diff --git a/src/coreclr/jit/regset.cpp b/src/coreclr/jit/regset.cpp index b87533c0e4e8f..2987d01b4f3d5 100644 --- a/src/coreclr/jit/regset.cpp +++ b/src/coreclr/jit/regset.cpp @@ -330,20 +330,30 @@ void RegSet::rsSpillTree(regNumber reg, GenTree* tree, unsigned regIdx /* =0 */) treeType = tree->TypeGet(); } - var_types tempType = RegSet::tmpNormalizeType(treeType); regMaskTP mask; bool floatSpill = false; if (isFloatRegType(treeType)) { - floatSpill = true; - mask = genRegMaskFloat(reg ARM_ARG(treeType)); +#ifdef TARGET_RISCV64 + if (genIsValidIntReg(reg)) + { + treeType = (treeType == TYP_FLOAT) ? TYP_INT : TYP_LONG; + mask = genRegMask(reg); + } + else +#endif // TARGET_RISCV64 + { + floatSpill = true; + mask = genRegMaskFloat(reg ARM_ARG(treeType)); + } } else { mask = genRegMask(reg); } + var_types tempType = RegSet::tmpNormalizeType(treeType); rsNeededSpillReg = true; // We should only be spilling nodes marked for spill, From 73523cf62d1047014bb7a0b4ca19d9741bdb6226 Mon Sep 17 00:00:00 2001 From: Dong-Heon Jung Date: Fri, 12 Jan 2024 17:03:31 +0900 Subject: [PATCH 07/22] [RISC-V] Update EPILOG_WITH_TRANSITION_BLOCK_RETURN --- src/coreclr/pal/inc/unixasmmacrosriscv64.inc | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/coreclr/pal/inc/unixasmmacrosriscv64.inc b/src/coreclr/pal/inc/unixasmmacrosriscv64.inc index cd61556a906e9..9363b16c60d41 100644 --- a/src/coreclr/pal/inc/unixasmmacrosriscv64.inc +++ b/src/coreclr/pal/inc/unixasmmacrosriscv64.inc @@ -293,8 +293,14 @@ C_FUNC(\Name\()_End): .endm .macro EPILOG_WITH_TRANSITION_BLOCK_RETURN -// TODO RISCV NYI - sw ra, 0(zero) + + RESTORE_CALLEESAVED_REGISTERS sp, __PWTB_CalleeSavedRegisters + + EPILOG_RESTORE_REG_PAIR fp, ra, __PWTB_CalleeSavedRegisters + + EPILOG_STACK_FREE __PWTB_StackAlloc + + ret .endm From 07a0f004926255a6aa2fce50b2c701a4cc0e6407 Mon Sep 17 00:00:00 2001 From: Dong-Heon Jung Date: Mon, 15 Jan 2024 17:11:02 +0900 Subject: [PATCH 08/22] [RISC-V] Update indentation in dump --- src/coreclr/jit/emitriscv64.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 179d0d8b0e9ec..eeb5ee59a3054 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -4049,6 +4049,12 @@ void emitter::emitDispIns( instrSize = sizeof(code_t); code_t instruction; memcpy(&instruction, instr, instrSize); +#ifdef DEBUG + if (emitComp->verbose && i != 0) + { + printf(" "); + } +#endif emitDispInsName(instruction, instr, doffs, offset, id, ig); } } From 7b73f4fcfca6ee6f9ed521bb34a9b52d84dfdd4b Mon Sep 17 00:00:00 2001 From: Dong-Heon Jung Date: Mon, 15 Jan 2024 17:41:24 +0900 Subject: [PATCH 09/22] [RISC-V] Fix stubs --- src/coreclr/vm/riscv64/stubs.cpp | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/coreclr/vm/riscv64/stubs.cpp b/src/coreclr/vm/riscv64/stubs.cpp index 42c0230509d70..13a6e4f21bbc0 100644 --- a/src/coreclr/vm/riscv64/stubs.cpp +++ b/src/coreclr/vm/riscv64/stubs.cpp @@ -1560,7 +1560,24 @@ PCODE DynamicHelpers::CreateHelper(LoaderAllocator * pAllocator, TADDR arg, PCOD BEGIN_DYNAMIC_HELPER_EMIT(32); - EmitHelperWithArg(p, rxOffset, pAllocator, arg, target); + const IntReg RegR0 = 0, RegT0 = 5, RegA0 = 10; + + *(DWORD*)p = UTypeInstr(0x17, RegT0, 0);// auipc t0, 0 + p += 4; + *(DWORD*)p = ITypeInstr(0x3, 0x3, RegA0, RegT0, 16);// ld a1, 16(t0) + p += 4; + *(DWORD*)p = ITypeInstr(0x3, 0x3, RegT0, RegT0, 24);;// ld t0, 24(t0) + p += 4; + *(DWORD*)p = ITypeInstr(0x67, 0, RegR0, RegT0, 0);// jalr zero, 0(t0) + p += 4; + + // label: + // arg + *(TADDR*)p = arg; + p += 8; + // target + *(PCODE*)p = target; + p += 8; END_DYNAMIC_HELPER_EMIT(); } @@ -1570,11 +1587,11 @@ void DynamicHelpers::EmitHelperWithArg(BYTE*& p, size_t rxOffset, LoaderAllocato { STANDARD_VM_CONTRACT; - const IntReg RegR0 = 0, RegT0 = 5, RegA0 = 10; + const IntReg RegR0 = 0, RegT0 = 5, RegA1 = 11; *(DWORD*)p = UTypeInstr(0x17, RegT0, 0);// auipc t0, 0 p += 4; - *(DWORD*)p = ITypeInstr(0x3, 0x3, RegA0, RegT0, 16);// ld a0, 16(t0) + *(DWORD*)p = ITypeInstr(0x3, 0x3, RegA1, RegT0, 16);// ld a1, 16(t0) p += 4; *(DWORD*)p = ITypeInstr(0x3, 0x3, RegT0, RegT0, 24);;// ld t0, 24(t0) p += 4; From d52b5c2eba77ce25d9813ce572bb4ebd73c77b29 Mon Sep 17 00:00:00 2001 From: Dong-Heon Jung Date: Mon, 15 Jan 2024 18:31:14 +0900 Subject: [PATCH 10/22] [RISC-V] Fix virtualcallstubcpu --- src/coreclr/vm/riscv64/virtualcallstubcpu.hpp | 46 ++++++++++++++----- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/src/coreclr/vm/riscv64/virtualcallstubcpu.hpp b/src/coreclr/vm/riscv64/virtualcallstubcpu.hpp index 0491dd880815b..0669610ae81df 100644 --- a/src/coreclr/vm/riscv64/virtualcallstubcpu.hpp +++ b/src/coreclr/vm/riscv64/virtualcallstubcpu.hpp @@ -372,8 +372,30 @@ struct VTableCallStub inline size_t size() { - _ASSERTE(!"RISCV64:NYI"); - return 0; + LIMITED_METHOD_CONTRACT; + + BYTE* pStubCode = (BYTE *)this; + + + if ((*(DWORD*)(&pStubCode[12])) == 0x000e8067) + { + // jalr x0, t4, 0 + return 20;//4*ins + slot = 4*4 + 4; + } + + //auipc t1, 0 + assert((*(DWORD*)(&pStubCode[4])) == 0x00000317); + + size_t cbSize = 36; + + // ld t4, 0(t4) + if ((*(DWORD*)(&pStubCode[16])) == 0x000ebe83) + { + if ((*(DWORD*)(&pStubCode[28])) == 0x000ebe83) + cbSize += 12; + } + + return cbSize; } inline PCODE entryPoint() const { LIMITED_METHOD_CONTRACT; return (PCODE)&_entryPoint[0]; } @@ -402,8 +424,8 @@ struct VTableCallHolder STATIC_CONTRACT_WRAPPER; unsigned offsetOfIndirection = MethodTable::GetVtableOffset() + MethodTable::GetIndexOfVtableIndirection(slot) * TARGET_POINTER_SIZE; unsigned offsetAfterIndirection = MethodTable::GetIndexAfterVtableIndirection(slot) * TARGET_POINTER_SIZE; - int indirectionsCodeSize = (offsetOfIndirection >= 0x1000 ? 12 : 4) + (offsetAfterIndirection >= 0x1000 ? 12 : 4); - int indirectionsDataSize = (offsetOfIndirection >= 0x1000 ? 4 : 0) + (offsetAfterIndirection >= 0x1000 ? 4 : 0); + int indirectionsCodeSize = (offsetOfIndirection > 2047 ? 12 : 4) + (offsetAfterIndirection > 2047 ? 12 : 4); + int indirectionsDataSize = (offsetOfIndirection > 2047 ? 4 : 0) + (offsetAfterIndirection > 2047 ? 4 : 0); return 12 + indirectionsCodeSize + ((indirectionsDataSize > 0) ? (indirectionsDataSize + 4) : 0); } @@ -444,15 +466,15 @@ void VTableCallHolder::Initialize(unsigned slot) *(UINT32*)p = 0x00053e83; // VTABLECALL_STUB_FIRST_DWORD p += 4; - if ((offsetOfIndirection >= 0x1000) || (offsetAfterIndirection >= 0x1000)) + if ((offsetOfIndirection > 2047) || (offsetAfterIndirection > 2047)) { *(UINT32*)p = 0x00000317; // auipc t1, 0 p += 4; } - if (offsetOfIndirection >= 0x1000) + if (offsetOfIndirection > 2047) { - uint dataOffset = 20 + (offsetAfterIndirection >= 0x1000 ? 12 : 4); + uint dataOffset = 20 + (offsetAfterIndirection > 2047 ? 12 : 4); // lwu t3,dataOffset(t1) *(DWORD*)p = 0x00036e03 | ((UINT32)dataOffset << 20); p += 4; @@ -467,10 +489,10 @@ void VTableCallHolder::Initialize(unsigned slot) *(DWORD*)p = 0x000ebe83 | ((UINT32)offsetOfIndirection << 20); p += 4; } - if (offsetAfterIndirection >= 0x1000) + if (offsetAfterIndirection > 2047) { - uint indirectionsCodeSize = (offsetOfIndirection >= 0x1000 ? 12 : 4); - uint indirectionsDataSize = (offsetOfIndirection >= 0x1000 ? 4 : 0); + uint indirectionsCodeSize = (offsetOfIndirection > 2047 ? 12 : 4); + uint indirectionsDataSize = (offsetOfIndirection > 2047 ? 4 : 0); uint dataOffset = 20 + indirectionsCodeSize + indirectionsDataSize; // ldw t3,dataOffset(t1) @@ -490,12 +512,12 @@ void VTableCallHolder::Initialize(unsigned slot) *(UINT32*)p = 0x000e8067; p += 4; // data labels: - if (offsetOfIndirection >= 0x1000) + if (offsetOfIndirection > 2047) { *(UINT32*)p = (UINT32)offsetOfIndirection; p += 4; } - if (offsetAfterIndirection >= 0x1000) + if (offsetAfterIndirection > 2047) { *(UINT32*)p = (UINT32)offsetAfterIndirection; p += 4; From 5d21c033597d5d4013d45c3352e3a6a7b9c149cc Mon Sep 17 00:00:00 2001 From: Dong-Heon Jung Date: Tue, 16 Jan 2024 21:54:23 +0900 Subject: [PATCH 11/22] [RISC-V] Update a comment --- src/coreclr/vm/riscv64/virtualcallstubcpu.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/vm/riscv64/virtualcallstubcpu.hpp b/src/coreclr/vm/riscv64/virtualcallstubcpu.hpp index 0669610ae81df..8372d5f0bc4c4 100644 --- a/src/coreclr/vm/riscv64/virtualcallstubcpu.hpp +++ b/src/coreclr/vm/riscv64/virtualcallstubcpu.hpp @@ -495,7 +495,7 @@ void VTableCallHolder::Initialize(unsigned slot) uint indirectionsDataSize = (offsetOfIndirection > 2047 ? 4 : 0); uint dataOffset = 20 + indirectionsCodeSize + indirectionsDataSize; - // ldw t3,dataOffset(t1) + // lwu t3,dataOffset(t1) *(DWORD*)p = 0x00036e03 | ((UINT32)dataOffset << 20); p += 4; // add t4, t4, t3 *(DWORD*)p = 0x01ce8eb3; p += 4; From d84ce77eccfa95e45d0ece9e7bd4d4185f1ba7b2 Mon Sep 17 00:00:00 2001 From: Dong-Heon Jung Date: Thu, 18 Jan 2024 18:16:15 +0900 Subject: [PATCH 12/22] [RISC-V] Update RO data block --- src/coreclr/jit/ee_il_dll.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/coreclr/jit/ee_il_dll.cpp b/src/coreclr/jit/ee_il_dll.cpp index 35983dcab7aae..e7506b91bf35b 100644 --- a/src/coreclr/jit/ee_il_dll.cpp +++ b/src/coreclr/jit/ee_il_dll.cpp @@ -1133,9 +1133,9 @@ void Compiler::eeAllocMem(AllocMemArgs* args, const UNATIVE_OFFSET roDataSection #endif // DEBUG -#if defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) +#if defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) - // For arm64/LoongArch64, we want to allocate JIT data always adjacent to code similar to what native compiler does. + // For arm64/LoongArch64/RISCV64, we want to allocate JIT data always adjacent to code similar to what native compiler does. // This way allows us to use a single `ldr` to access such data like float constant/jmp table. // For LoongArch64 using `pcaddi + ld` to access such data. @@ -1149,7 +1149,7 @@ void Compiler::eeAllocMem(AllocMemArgs* args, const UNATIVE_OFFSET roDataSection args->hotCodeSize = roDataOffset + args->roDataSize; args->roDataSize = 0; -#endif // defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) +#endif // defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_LOONGARCH64) info.compCompHnd->allocMem(args); @@ -1166,7 +1166,7 @@ void Compiler::eeAllocMem(AllocMemArgs* args, const UNATIVE_OFFSET roDataSection #endif // DEBUG -#if defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) +#if defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) // Fix up data section pointers. assert(args->roDataBlock == nullptr); @@ -1174,7 +1174,7 @@ void Compiler::eeAllocMem(AllocMemArgs* args, const UNATIVE_OFFSET roDataSection args->roDataBlock = ((BYTE*)args->hotCodeBlock) + roDataOffset; args->roDataBlockRW = ((BYTE*)args->hotCodeBlockRW) + roDataOffset; -#endif // defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) +#endif // defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) } void Compiler::eeReserveUnwindInfo(bool isFunclet, bool isColdCode, ULONG unwindSize) From 6e6c4579ddacb0d5ec2d3cb4aa2751f7b2d75f4e Mon Sep 17 00:00:00 2001 From: Dong-Heon Jung Date: Fri, 19 Jan 2024 09:53:20 +0900 Subject: [PATCH 13/22] [RISC-V] Fix data overwrites --- src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index d53f8916a59b0..9b1bccaeffcea 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -412,9 +412,10 @@ private CompilationResult CompileMethodInternal(IMethodNode methodCodeNodeNeedin if (codeSize < _code.Length) { - if (_compilation.TypeSystemContext.Target.Architecture != TargetArchitecture.ARM64) + if (_compilation.TypeSystemContext.Target.Architecture != TargetArchitecture.ARM64 + && _compilation.TypeSystemContext.Target.Architecture != TargetArchitecture.RiscV64) { - // For xarch/arm32, the generated code is sometimes smaller than the memory allocated. + // For xarch/arm32/RiscV64, the generated code is sometimes smaller than the memory allocated. // In that case, trim the codeBlock to the actual value. // // For arm64, the allocation request of `hotCodeSize` also includes the roData size From 60858e0976ec58dd455dec5a0416cf8780db40c4 Mon Sep 17 00:00:00 2001 From: Dong-Heon Jung Date: Fri, 19 Jan 2024 16:36:10 +0900 Subject: [PATCH 14/22] [RISC-V] Fix typo --- src/coreclr/jit/ee_il_dll.cpp | 2 +- src/coreclr/jit/emitriscv64.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/jit/ee_il_dll.cpp b/src/coreclr/jit/ee_il_dll.cpp index e7506b91bf35b..848fc23d97530 100644 --- a/src/coreclr/jit/ee_il_dll.cpp +++ b/src/coreclr/jit/ee_il_dll.cpp @@ -1149,7 +1149,7 @@ void Compiler::eeAllocMem(AllocMemArgs* args, const UNATIVE_OFFSET roDataSection args->hotCodeSize = roDataOffset + args->roDataSize; args->roDataSize = 0; -#endif // defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_LOONGARCH64) +#endif // defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) info.compCompHnd->allocMem(args); diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index eeb5ee59a3054..82384d0ae37a5 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -1423,7 +1423,7 @@ void emitter::emitIns_Call(EmitCallType callType, assert(callType == EC_FUNC_TOKEN); assert(addr != NULL); - addr = (void*)(((size_t)addr) + (isJump ? 0 : 1)); // NOTE: low-bit0 is used for jirl ra/r0,rd,0 + addr = (void*)(((size_t)addr) + (isJump ? 0 : 1)); // NOTE: low-bit0 is used for jalr ra/r0,rd,0 id->idAddr()->iiaAddr = (BYTE*)addr; if (emitComp->opts.compReloc) From 00ce57f11d22b5535228eebbcef452d7baffd077 Mon Sep 17 00:00:00 2001 From: Dong-Heon Jung Date: Fri, 19 Jan 2024 21:11:55 +0900 Subject: [PATCH 15/22] [RISC-V] Fix register number of A3 --- src/coreclr/vm/riscv64/stubs.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/vm/riscv64/stubs.cpp b/src/coreclr/vm/riscv64/stubs.cpp index 13a6e4f21bbc0..5ed5a66850daf 100644 --- a/src/coreclr/vm/riscv64/stubs.cpp +++ b/src/coreclr/vm/riscv64/stubs.cpp @@ -1789,7 +1789,7 @@ PCODE DynamicHelpers::CreateHelperWithTwoArgs(LoaderAllocator * pAllocator, TADD BEGIN_DYNAMIC_HELPER_EMIT(48); - const IntReg RegR0 = 0, RegT0 = 5, RegA2 = 12, RegA3 = 1; + const IntReg RegR0 = 0, RegT0 = 5, RegA2 = 12, RegA3 = 13; *(DWORD*)p = UTypeInstr(0x17, RegT0, 0);// auipc t0, 0 p += 4; @@ -1797,7 +1797,7 @@ PCODE DynamicHelpers::CreateHelperWithTwoArgs(LoaderAllocator * pAllocator, TADD p += 4; *(DWORD*)p = ITypeInstr(0x3, 0x3, RegA3, RegT0, 32);// ld a3,32(t0) p += 4; - *(DWORD*)p = ITypeInstr(0x3, 0x3, RegT0, RegT0, 40);;// ld t0,40(t0) + *(DWORD*)p = ITypeInstr(0x3, 0x3, RegT0, RegT0, 40);// ld t0,40(t0) p += 4; *(DWORD*)p = ITypeInstr(0x67, 0, RegR0, RegT0, 0);// jalr x0, 0(t0) p += 4; From f575d0ab2a0172b92ed6199f9c43028fb7179c43 Mon Sep 17 00:00:00 2001 From: Dong-Heon Jung Date: Tue, 23 Jan 2024 17:05:47 +0900 Subject: [PATCH 16/22] [RISC-V] Code Formatting --- src/coreclr/pal/inc/unixasmmacrosriscv64.inc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/pal/inc/unixasmmacrosriscv64.inc b/src/coreclr/pal/inc/unixasmmacrosriscv64.inc index 9363b16c60d41..af7e5336ec647 100644 --- a/src/coreclr/pal/inc/unixasmmacrosriscv64.inc +++ b/src/coreclr/pal/inc/unixasmmacrosriscv64.inc @@ -296,9 +296,9 @@ C_FUNC(\Name\()_End): RESTORE_CALLEESAVED_REGISTERS sp, __PWTB_CalleeSavedRegisters - EPILOG_RESTORE_REG_PAIR fp, ra, __PWTB_CalleeSavedRegisters + EPILOG_RESTORE_REG_PAIR fp, ra, __PWTB_CalleeSavedRegisters - EPILOG_STACK_FREE __PWTB_StackAlloc + EPILOG_STACK_FREE __PWTB_StackAlloc ret .endm From 0f9ac89fa798c4743a45d4f6b3bc79541e2538a3 Mon Sep 17 00:00:00 2001 From: Dong-Heon Jung Date: Tue, 23 Jan 2024 17:38:57 +0900 Subject: [PATCH 17/22] [RISC-V] Fix format and typos --- src/coreclr/jit/codegenlinear.cpp | 5 +++-- src/coreclr/jit/ee_il_dll.cpp | 3 ++- src/coreclr/jit/regset.cpp | 6 +++--- src/coreclr/vm/riscv64/stubs.cpp | 4 ++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/coreclr/jit/codegenlinear.cpp b/src/coreclr/jit/codegenlinear.cpp index b41b24f2a3a5c..d66986bb55100 100644 --- a/src/coreclr/jit/codegenlinear.cpp +++ b/src/coreclr/jit/codegenlinear.cpp @@ -1310,7 +1310,7 @@ void CodeGen::genUnspillRegIfNeeded(GenTree* tree) // The spill temp allocated for it is associated with the original tree that defined the // register that it was spilled from. // So we use 'unspillTree' to recover that spill temp. - TempDsc* t = regSet.rsUnspillInPlace(unspillTree, unspillTree->GetRegNum()); + TempDsc* t = regSet.rsUnspillInPlace(unspillTree, unspillTree->GetRegNum()); var_types unspillType = unspillTree->TypeGet(); // Reload into the register specified by 'tree' which may be a GT_RELOAD. @@ -1321,7 +1321,8 @@ void CodeGen::genUnspillRegIfNeeded(GenTree* tree) unspillType = (unspillType == TYP_FLOAT) ? TYP_INT : TYP_LONG; } #endif // TARGET_RISCV64 - GetEmitter()->emitIns_R_S(ins_Load(unspillType), emitActualTypeSize(unspillType), dstReg, t->tdTempNum(), 0); + GetEmitter()->emitIns_R_S(ins_Load(unspillType), emitActualTypeSize(unspillType), dstReg, t->tdTempNum(), + 0); regSet.tmpRlsTemp(t); unspillTree->gtFlags &= ~GTF_SPILLED; diff --git a/src/coreclr/jit/ee_il_dll.cpp b/src/coreclr/jit/ee_il_dll.cpp index 848fc23d97530..6fa3b32f8cead 100644 --- a/src/coreclr/jit/ee_il_dll.cpp +++ b/src/coreclr/jit/ee_il_dll.cpp @@ -1135,7 +1135,8 @@ void Compiler::eeAllocMem(AllocMemArgs* args, const UNATIVE_OFFSET roDataSection #if defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) - // For arm64/LoongArch64/RISCV64, we want to allocate JIT data always adjacent to code similar to what native compiler does. + // For arm64/LoongArch64/RISCV64, we want to allocate JIT data always adjacent to code similar to what native + // compiler does. // This way allows us to use a single `ldr` to access such data like float constant/jmp table. // For LoongArch64 using `pcaddi + ld` to access such data. diff --git a/src/coreclr/jit/regset.cpp b/src/coreclr/jit/regset.cpp index 2987d01b4f3d5..56f80494f6b90 100644 --- a/src/coreclr/jit/regset.cpp +++ b/src/coreclr/jit/regset.cpp @@ -338,8 +338,8 @@ void RegSet::rsSpillTree(regNumber reg, GenTree* tree, unsigned regIdx /* =0 */) #ifdef TARGET_RISCV64 if (genIsValidIntReg(reg)) { - treeType = (treeType == TYP_FLOAT) ? TYP_INT : TYP_LONG; - mask = genRegMask(reg); + treeType = (treeType == TYP_FLOAT) ? TYP_INT : TYP_LONG; + mask = genRegMask(reg); } else #endif // TARGET_RISCV64 @@ -354,7 +354,7 @@ void RegSet::rsSpillTree(regNumber reg, GenTree* tree, unsigned regIdx /* =0 */) } var_types tempType = RegSet::tmpNormalizeType(treeType); - rsNeededSpillReg = true; + rsNeededSpillReg = true; // We should only be spilling nodes marked for spill, // vars should be handled elsewhere, and to prevent diff --git a/src/coreclr/vm/riscv64/stubs.cpp b/src/coreclr/vm/riscv64/stubs.cpp index 5ed5a66850daf..e4b504238211b 100644 --- a/src/coreclr/vm/riscv64/stubs.cpp +++ b/src/coreclr/vm/riscv64/stubs.cpp @@ -1566,7 +1566,7 @@ PCODE DynamicHelpers::CreateHelper(LoaderAllocator * pAllocator, TADDR arg, PCOD p += 4; *(DWORD*)p = ITypeInstr(0x3, 0x3, RegA0, RegT0, 16);// ld a1, 16(t0) p += 4; - *(DWORD*)p = ITypeInstr(0x3, 0x3, RegT0, RegT0, 24);;// ld t0, 24(t0) + *(DWORD*)p = ITypeInstr(0x3, 0x3, RegT0, RegT0, 24);// ld t0, 24(t0) p += 4; *(DWORD*)p = ITypeInstr(0x67, 0, RegR0, RegT0, 0);// jalr zero, 0(t0) p += 4; @@ -1593,7 +1593,7 @@ void DynamicHelpers::EmitHelperWithArg(BYTE*& p, size_t rxOffset, LoaderAllocato p += 4; *(DWORD*)p = ITypeInstr(0x3, 0x3, RegA1, RegT0, 16);// ld a1, 16(t0) p += 4; - *(DWORD*)p = ITypeInstr(0x3, 0x3, RegT0, RegT0, 24);;// ld t0, 24(t0) + *(DWORD*)p = ITypeInstr(0x3, 0x3, RegT0, RegT0, 24);// ld t0, 24(t0) p += 4; *(DWORD*)p = ITypeInstr(0x67, 0, RegR0, RegT0, 0);// jalr zero, 0(t0) p += 4; From 6bc960675e3fb5d7ffc083e27d6bb1b4ae21b060 Mon Sep 17 00:00:00 2001 From: Dong-Heon Jung Date: Thu, 25 Jan 2024 18:53:01 +0900 Subject: [PATCH 18/22] Revert "[RISC-V] Fix int arg reg passing for float type" This reverts commit 381858cb2335782d66e8a6439db9c6f053adff21. --- src/coreclr/jit/codegenlinear.cpp | 18 +++++------------- src/coreclr/jit/lsra.cpp | 6 ------ src/coreclr/jit/regset.cpp | 18 ++++-------------- 3 files changed, 9 insertions(+), 33 deletions(-) diff --git a/src/coreclr/jit/codegenlinear.cpp b/src/coreclr/jit/codegenlinear.cpp index d66986bb55100..67f4bb73c0eb1 100644 --- a/src/coreclr/jit/codegenlinear.cpp +++ b/src/coreclr/jit/codegenlinear.cpp @@ -1258,7 +1258,7 @@ void CodeGen::genUnspillRegIfNeeded(GenTree* tree) unspillType = lcl->TypeGet(); } -#if defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) +#if defined(TARGET_LOONGARCH64) if (varTypeIsFloating(unspillType) && emitter::isGeneralRegister(tree->GetRegNum())) { unspillType = unspillType == TYP_FLOAT ? TYP_INT : TYP_LONG; @@ -1310,23 +1310,15 @@ void CodeGen::genUnspillRegIfNeeded(GenTree* tree) // The spill temp allocated for it is associated with the original tree that defined the // register that it was spilled from. // So we use 'unspillTree' to recover that spill temp. - TempDsc* t = regSet.rsUnspillInPlace(unspillTree, unspillTree->GetRegNum()); - var_types unspillType = unspillTree->TypeGet(); - + TempDsc* t = regSet.rsUnspillInPlace(unspillTree, unspillTree->GetRegNum()); + emitAttr emitType = emitActualTypeSize(unspillTree->TypeGet()); // Reload into the register specified by 'tree' which may be a GT_RELOAD. regNumber dstReg = tree->GetRegNum(); -#ifdef TARGET_RISCV64 - if (varTypeIsFloating(unspillType) && emitter::isGeneralRegister(dstReg)) - { - unspillType = (unspillType == TYP_FLOAT) ? TYP_INT : TYP_LONG; - } -#endif // TARGET_RISCV64 - GetEmitter()->emitIns_R_S(ins_Load(unspillType), emitActualTypeSize(unspillType), dstReg, t->tdTempNum(), - 0); + GetEmitter()->emitIns_R_S(ins_Load(unspillTree->gtType), emitType, dstReg, t->tdTempNum(), 0); regSet.tmpRlsTemp(t); unspillTree->gtFlags &= ~GTF_SPILLED; - gcInfo.gcMarkRegPtrVal(dstReg, unspillType); + gcInfo.gcMarkRegPtrVal(dstReg, unspillTree->TypeGet()); } } } diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp index caecef1b795db..37d85e23b9150 100644 --- a/src/coreclr/jit/lsra.cpp +++ b/src/coreclr/jit/lsra.cpp @@ -7045,12 +7045,6 @@ void LinearScan::updateMaxSpill(RefPosition* refPosition) if (!treeNode->IsMultiRegNode()) { type = getDefType(treeNode); -#ifdef TARGET_RISCV64 - if (isFloatRegType(type) && genIsValidIntReg(treeNode->GetRegNum())) - { - type = (type == TYP_FLOAT) ? TYP_INT : TYP_LONG; - } -#endif // TARGET_RISCV64 } else { diff --git a/src/coreclr/jit/regset.cpp b/src/coreclr/jit/regset.cpp index 56f80494f6b90..b87533c0e4e8f 100644 --- a/src/coreclr/jit/regset.cpp +++ b/src/coreclr/jit/regset.cpp @@ -330,31 +330,21 @@ void RegSet::rsSpillTree(regNumber reg, GenTree* tree, unsigned regIdx /* =0 */) treeType = tree->TypeGet(); } + var_types tempType = RegSet::tmpNormalizeType(treeType); regMaskTP mask; bool floatSpill = false; if (isFloatRegType(treeType)) { -#ifdef TARGET_RISCV64 - if (genIsValidIntReg(reg)) - { - treeType = (treeType == TYP_FLOAT) ? TYP_INT : TYP_LONG; - mask = genRegMask(reg); - } - else -#endif // TARGET_RISCV64 - { - floatSpill = true; - mask = genRegMaskFloat(reg ARM_ARG(treeType)); - } + floatSpill = true; + mask = genRegMaskFloat(reg ARM_ARG(treeType)); } else { mask = genRegMask(reg); } - var_types tempType = RegSet::tmpNormalizeType(treeType); - rsNeededSpillReg = true; + rsNeededSpillReg = true; // We should only be spilling nodes marked for spill, // vars should be handled elsewhere, and to prevent From 2799636d4a2d6f4ad71f510ebb0b69d69f8b2145 Mon Sep 17 00:00:00 2001 From: Dong-Heon Jung Date: Thu, 25 Jan 2024 19:37:12 +0900 Subject: [PATCH 19/22] [RISC-V] Fix a typo in a comment --- src/coreclr/vm/riscv64/stubs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/vm/riscv64/stubs.cpp b/src/coreclr/vm/riscv64/stubs.cpp index e4b504238211b..0f0273da0a47b 100644 --- a/src/coreclr/vm/riscv64/stubs.cpp +++ b/src/coreclr/vm/riscv64/stubs.cpp @@ -1564,7 +1564,7 @@ PCODE DynamicHelpers::CreateHelper(LoaderAllocator * pAllocator, TADDR arg, PCOD *(DWORD*)p = UTypeInstr(0x17, RegT0, 0);// auipc t0, 0 p += 4; - *(DWORD*)p = ITypeInstr(0x3, 0x3, RegA0, RegT0, 16);// ld a1, 16(t0) + *(DWORD*)p = ITypeInstr(0x3, 0x3, RegA0, RegT0, 16);// ld a0, 16(t0) p += 4; *(DWORD*)p = ITypeInstr(0x3, 0x3, RegT0, RegT0, 24);// ld t0, 24(t0) p += 4; From 541ae4cb56c741e5406b502eb0698966c79c5c60 Mon Sep 17 00:00:00 2001 From: Dong-Heon Jung Date: Fri, 26 Jan 2024 16:30:47 +0900 Subject: [PATCH 20/22] [RISC-V] Fix error when arg type and arg reg mismatch --- src/coreclr/jit/gentree.h | 9 +++++++++ src/coreclr/jit/lower.cpp | 5 +++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index ae3ccc806c4b5..70c435698adee 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -4583,6 +4583,15 @@ struct CallArgABIInformation #endif } + bool IsMismatchArgType() const + { +#ifdef TARGET_RISCV64 + return isValidIntArgReg(GetRegNum()) && varTypeUsesFloatReg(ArgType); +#else + return false; +#endif // TARGET_RISCV64 + } + void SetByteSize(unsigned byteSize, unsigned byteAlignment, bool isStruct, bool isFloatHfa); // Get the number of bytes that this argument is occupying on the stack, diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index 27079d52e3bfb..8da2d06a819fd 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -1677,9 +1677,10 @@ void Lowering::LowerArg(GenTreeCall* call, CallArg* callArg, bool late) { #if defined(TARGET_ARMARCH) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) - if (call->IsVarargs() || comp->opts.compUseSoftFP) + if (call->IsVarargs() || comp->opts.compUseSoftFP || callArg->AbiInfo.IsMismatchArgType()) { // For vararg call or on armel, reg args should be all integer. + // For arg type and arg reg mismatch, reg arg should be integer on riscv64 // Insert copies as needed to move float value to integer register. GenTree* newNode = LowerFloatArg(ppArg, callArg); if (newNode != nullptr) @@ -1710,7 +1711,7 @@ void Lowering::LowerArg(GenTreeCall* call, CallArg* callArg, bool late) #if defined(TARGET_ARMARCH) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) //------------------------------------------------------------------------ -// LowerFloatArg: Lower float call arguments on the arm/LoongArch64 platform. +// LowerFloatArg: Lower float call arguments on the arm/LoongArch64/RiscV64 platform. // // Arguments: // arg - The arg node From 7c2b84d5ef0b5a29aa7b7aad0697379dfd5bf29e Mon Sep 17 00:00:00 2001 From: Dong-Heon Jung Date: Fri, 26 Jan 2024 20:19:21 +0900 Subject: [PATCH 21/22] [RISC-V] Rename according to review --- src/coreclr/jit/gentree.h | 2 +- src/coreclr/jit/lower.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index 70c435698adee..19224dc831c64 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -4583,7 +4583,7 @@ struct CallArgABIInformation #endif } - bool IsMismatchArgType() const + bool IsMismatchedArgType() const { #ifdef TARGET_RISCV64 return isValidIntArgReg(GetRegNum()) && varTypeUsesFloatReg(ArgType); diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index 8da2d06a819fd..e4b7561647ad2 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -1677,7 +1677,7 @@ void Lowering::LowerArg(GenTreeCall* call, CallArg* callArg, bool late) { #if defined(TARGET_ARMARCH) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) - if (call->IsVarargs() || comp->opts.compUseSoftFP || callArg->AbiInfo.IsMismatchArgType()) + if (call->IsVarargs() || comp->opts.compUseSoftFP || callArg->AbiInfo.IsMismatchedArgType()) { // For vararg call or on armel, reg args should be all integer. // For arg type and arg reg mismatch, reg arg should be integer on riscv64 From 0ce2d8c4fb712c7508ce0b9f9e8a1b5d57c84010 Mon Sep 17 00:00:00 2001 From: Dong-Heon Jung Date: Mon, 29 Jan 2024 16:35:11 +0900 Subject: [PATCH 22/22] [LoongArch64] Remove LA64 speicific handling for unspilling --- src/coreclr/jit/codegenlinear.cpp | 7 ------- src/coreclr/jit/gentree.h | 4 ++-- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/coreclr/jit/codegenlinear.cpp b/src/coreclr/jit/codegenlinear.cpp index 67f4bb73c0eb1..8ab28407d2a5d 100644 --- a/src/coreclr/jit/codegenlinear.cpp +++ b/src/coreclr/jit/codegenlinear.cpp @@ -1258,13 +1258,6 @@ void CodeGen::genUnspillRegIfNeeded(GenTree* tree) unspillType = lcl->TypeGet(); } -#if defined(TARGET_LOONGARCH64) - if (varTypeIsFloating(unspillType) && emitter::isGeneralRegister(tree->GetRegNum())) - { - unspillType = unspillType == TYP_FLOAT ? TYP_INT : TYP_LONG; - } -#endif - bool reSpill = ((unspillTree->gtFlags & GTF_SPILL) != 0); bool isLastUse = lcl->IsLastUse(0); genUnspillLocal(lcl->GetLclNum(), unspillType, lcl->AsLclVar(), tree->GetRegNum(), reSpill, isLastUse); diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index 19224dc831c64..4c52d0b2ab2ed 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -4585,11 +4585,11 @@ struct CallArgABIInformation bool IsMismatchedArgType() const { -#ifdef TARGET_RISCV64 +#if defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) return isValidIntArgReg(GetRegNum()) && varTypeUsesFloatReg(ArgType); #else return false; -#endif // TARGET_RISCV64 +#endif // TARGET_LOONGARCH64 || TARGET_RISCV64 } void SetByteSize(unsigned byteSize, unsigned byteAlignment, bool isStruct, bool isFloatHfa);