From aed5c225ded0fecf98988ac3736d0f6399a82df3 Mon Sep 17 00:00:00 2001 From: Sun Lijun Date: Wed, 10 Jul 2024 19:50:52 +0800 Subject: [PATCH] [LoongArch64] Amend the nativeaot for LoongArch64. (#104653) This PR fix several mistakes in nativeaot on LoongArch64: 1. Compilation error in debug mode. 2. The order of `m_RIP` and `m_FramePointer` in `struct PInvokeTransitionFrame`. 3. Add the test for invalid entries in `EmitDictionaryLookup`, in `class ReadyToRunGenericHelperNode`. The changes have been tested and verified to be successful. --- src/coreclr/nativeaot/Runtime/inc/rhbinder.h | 4 ++-- .../nativeaot/Runtime/loongarch64/AsmOffsetsCpu.h | 4 ++-- .../nativeaot/Runtime/loongarch64/ExceptionHandling.S | 6 +++--- .../LoongArch64ReadyToRunGenericHelperNode.cs | 11 +++++++++++ .../JitInterface/CorInfoImpl.RyuJit.cs | 4 ++-- 5 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/inc/rhbinder.h b/src/coreclr/nativeaot/Runtime/inc/rhbinder.h index f72ff28caf001..db238e24acbc1 100644 --- a/src/coreclr/nativeaot/Runtime/inc/rhbinder.h +++ b/src/coreclr/nativeaot/Runtime/inc/rhbinder.h @@ -461,8 +461,8 @@ struct PInvokeTransitionFrame #else // USE_PORTABLE_HELPERS struct PInvokeTransitionFrame { -#if defined(TARGET_ARM64) || defined(TARGET_ARM) - // On arm32/arm64, the FP and LR registers are pushed in that order when setting up frames +#if defined(TARGET_ARM64) || defined(TARGET_ARM) || defined(TARGET_LOONGARCH64) + // The FP and LR registers are pushed in different order when setting up frames TgtPTR_Void m_FramePointer; TgtPTR_Void m_RIP; #else diff --git a/src/coreclr/nativeaot/Runtime/loongarch64/AsmOffsetsCpu.h b/src/coreclr/nativeaot/Runtime/loongarch64/AsmOffsetsCpu.h index 0724e0f86fcff..ecc7eefd3ac4c 100644 --- a/src/coreclr/nativeaot/Runtime/loongarch64/AsmOffsetsCpu.h +++ b/src/coreclr/nativeaot/Runtime/loongarch64/AsmOffsetsCpu.h @@ -17,8 +17,8 @@ PLAT_ASM_OFFSET(1c, ExInfo, m_idxCurClause) PLAT_ASM_OFFSET(20, ExInfo, m_frameIter) PLAT_ASM_OFFSET(278, ExInfo, m_notifyDebuggerSP) -PLAT_ASM_OFFSET(8, PInvokeTransitionFrame, m_FramePointer) -PLAT_ASM_OFFSET(0, PInvokeTransitionFrame, m_RIP) +PLAT_ASM_OFFSET(0, PInvokeTransitionFrame, m_FramePointer) +PLAT_ASM_OFFSET(8, PInvokeTransitionFrame, m_RIP) PLAT_ASM_OFFSET(10, PInvokeTransitionFrame, m_pThread) PLAT_ASM_OFFSET(18, PInvokeTransitionFrame, m_Flags) PLAT_ASM_OFFSET(20, PInvokeTransitionFrame, m_PreservedRegs) diff --git a/src/coreclr/nativeaot/Runtime/loongarch64/ExceptionHandling.S b/src/coreclr/nativeaot/Runtime/loongarch64/ExceptionHandling.S index 7cd047c126348..461480f46d438 100644 --- a/src/coreclr/nativeaot/Runtime/loongarch64/ExceptionHandling.S +++ b/src/coreclr/nativeaot/Runtime/loongarch64/ExceptionHandling.S @@ -181,10 +181,10 @@ .macro TRASH_PRESERVED_REGISTERS_STORAGE regdisplayReg #if _DEBUG - lu12i.w $a3, 0xbaadd + lu12i.w $a3, -283939 // 0xbaadd ori $a3, $a3, 0xeed - lu32i.d $a3, 0xddeed - lu52i.d $a3, $a3, 0xbaa + lu32i.d $a3, -139539 // 0xddeed + lu52i.d $a3, $a3, -1110 // 0xbaa ld.d $t3, \regdisplayReg, OFFSETOF__REGDISPLAY__pR23 st.d $a3, $t3, 0 ld.d $t3, \regdisplayReg, OFFSETOF__REGDISPLAY__pR24 diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_LoongArch64/LoongArch64ReadyToRunGenericHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_LoongArch64/LoongArch64ReadyToRunGenericHelperNode.cs index 374062c2f07a8..6d68882ae8317 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_LoongArch64/LoongArch64ReadyToRunGenericHelperNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_LoongArch64/LoongArch64ReadyToRunGenericHelperNode.cs @@ -39,6 +39,17 @@ protected void EmitDictionaryLookup(NodeFactory factory, ref LoongArch64Emitter // Load the generic dictionary cell encoder.EmitLD(result, context, dictionarySlot * factory.Target.PointerSize); + + // If there's any invalid entries, we need to test for them + // + // Skip this in relocsOnly to make it easier to weed out bugs - the _hasInvalidEntries + // flag can change over the course of compilation and the bad slot helper dependency + // should be reported by someone else - the system should not rely on it coming from here. + if (!relocsOnly && _hasInvalidEntries) + { + encoder.EmitXOR(encoder.TargetRegister.IntraProcedureCallScratch1, result, 0); + encoder.EmitJE(encoder.TargetRegister.IntraProcedureCallScratch1, GetBadSlotHelper(factory)); + } } protected sealed override void EmitCode(NodeFactory factory, ref LoongArch64Emitter encoder, bool relocsOnly) diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index 3ce82beeac667..317452b4f2b9a 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -2001,12 +2001,12 @@ private int SizeOfPInvokeTransitionFrame // m_RIP (1) // m_FramePointer (1) // m_pThread - // m_Flags + align (no align for ARM64 that has 64 bit m_Flags) + // m_Flags + align (no align for ARM64/LoongArch64 that has 64 bit m_Flags) // m_PreservedRegs - RSP / R9 (2) // No need to save other preserved regs because of the JIT ensures that there are // no live GC references in callee saved registers around the PInvoke callsite. // - // (1) On ARM32/ARM64 the order of m_RIP and m_FramePointer is reverse + // (1) On ARM32/ARM64/LoongArch64 the order of m_RIP and m_FramePointer is reverse // (2) R9 is saved for ARM32 because it needs to be preserved for methods with stackalloc int size = 5 * this.PointerSize;