Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/coreclr/clr.featuredefines.props
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
<FeatureInterpreter>true</FeatureInterpreter>
</PropertyGroup>

<PropertyGroup Condition="('$(Platform)' == 'x64' OR '$(Platform)' == 'arm64' OR '$(Platform)' == 'arm' OR '$(Platform)' == 'riscv64') AND ('$(Configuration)' == 'debug' OR '$(Configuration)' == 'checked') AND '$(TargetsAndroid)' != 'true'">
<PropertyGroup Condition="('$(Platform)' == 'x64' OR '$(Platform)' == 'arm64' OR '$(Platform)' == 'arm' OR '$(Platform)' == 'riscv64' OR '$(Platform)' == 'loongarch64') AND ('$(Configuration)' == 'debug' OR '$(Configuration)' == 'checked') AND '$(TargetsAndroid)' != 'true'">
<FeatureInterpreter>true</FeatureInterpreter>
</PropertyGroup>

Expand Down
19 changes: 10 additions & 9 deletions src/coreclr/clrfeatures.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,17 @@ if(CLR_CMAKE_TARGET_BROWSER)
endif()

if(NOT DEFINED FEATURE_INTERPRETER)
if(CLR_CMAKE_TARGET_ANDROID)
set(FEATURE_INTERPRETER 0)
else()
if(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64 OR CLR_CMAKE_TARGET_ARCH_ARM OR CLR_CMAKE_TARGET_ARCH_RISCV64)
set(FEATURE_INTERPRETER $<IF:$<CONFIG:Debug,Checked>,1,0>)
else(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64 OR CLR_CMAKE_TARGET_ARCH_ARM OR CLR_CMAKE_TARGET_ARCH_RISCV64)
set(FEATURE_INTERPRETER 0)
endif(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64 OR CLR_CMAKE_TARGET_ARCH_ARM OR CLR_CMAKE_TARGET_ARCH_RISCV64)
set(FEATURE_INTERPRETER 0)

if(NOT CLR_CMAKE_TARGET_ANDROID AND
(CLR_CMAKE_TARGET_ARCH_AMD64 OR
CLR_CMAKE_TARGET_ARCH_ARM64 OR
CLR_CMAKE_TARGET_ARCH_ARM OR
CLR_CMAKE_TARGET_ARCH_RISCV64 OR
CLR_CMAKE_TARGET_ARCH_LOONGARCH64))
set(FEATURE_INTERPRETER $<IF:$<CONFIG:Debug,Checked>,1,0>)
endif()
endif(NOT DEFINED FEATURE_INTERPRETER)
endif()

if(NOT DEFINED FEATURE_STANDALONE_GC)
set(FEATURE_STANDALONE_GC 1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,28 +143,7 @@ C_FUNC(\Name):

.endm

// Loads the address of a thread-local variable into the target register,
// which cannot be a0. Preserves all other registers.
.macro INLINE_GET_TLS_VAR target, var
.ifc \target, $a0
.error "target cannot be a0"
.endif

addi.d $sp, $sp, -16
st.d $a0, $sp, 0
st.d $ra, $sp, 8

// This instruction is recognized and potentially patched
// by the linker (GD->IE/LE relaxation).
la.tls.desc $a0, \var

ori \target, $tp, 0
add.d \target, \target, $a0

ld.d $a0, $sp, 0
ld.d $ra, $sp, 8
addi.d $sp, $sp, 16
.endm
#include <loongarch64/InlineTls.inc>

// Inlined version of RhpGetThread. Target cannot be a0.
.macro INLINE_GETTHREAD target
Expand Down
8 changes: 8 additions & 0 deletions src/coreclr/pal/inc/unixasmmacrosloongarch64.inc
Original file line number Diff line number Diff line change
Expand Up @@ -523,3 +523,11 @@ $__RedirectionStubEndFuncName
0:
#endif
.endm

#include <loongarch64/InlineTls.inc>

// Inlined version of RhpGetThread. Target cannot be a0.
.macro INLINE_GETTHREAD target
INLINE_GET_TLS_VAR \target, C_FUNC(t_CurrentThreadInfo)
ld.d \target, \target, OFFSETOF__ThreadLocalInfo__m_pThread
.endm
25 changes: 25 additions & 0 deletions src/coreclr/runtime/loongarch64/InlineTls.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

// Loads the address of a thread-local variable into the target register,
// which cannot be a0. Preserves all other registers.
.macro INLINE_GET_TLS_VAR target, var
.ifc \target, $a0
.error "target cannot be a0"
.endif

addi.d $sp, $sp, -16
st.d $a0, $sp, 0
st.d $ra, $sp, 8

// This instruction is recognized and potentially patched
// by the linker (GD->IE/LE relaxation).
la.tls.desc $a0, \var

ori \target, $tp, 0
add.d \target, \target, $a0

ld.d $a0, $sp, 0
ld.d $ra, $sp, 8
addi.d $sp, $sp, 16
.endm
52 changes: 33 additions & 19 deletions src/coreclr/vm/callstubgenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,7 @@ extern "C" void Store_Stack_4B();

#endif // TARGET_ARM

#ifdef TARGET_RISCV64
#if defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64)

extern "C" void Load_A0();
extern "C" void Load_A0_A1();
Expand Down Expand Up @@ -783,7 +783,7 @@ extern "C" void Store_FA6();
extern "C" void Store_FA6_FA7();
extern "C" void Store_FA7();

#endif // TARGET_RISCV64
#endif // TARGET_RISCV64 || TARGET_LOONGARCH64

PCODE CallStubGenerator::GetStackRoutine()
{
Expand Down Expand Up @@ -879,7 +879,7 @@ PCODE CallStubGenerator::GetGPRegRangeRoutine(int r1, int r2)
(PCODE)0, (PCODE)0, (PCODE)Store_R2, (PCODE)Store_R2_R3,
(PCODE)0, (PCODE)0, (PCODE)0, (PCODE)Store_R3
};
#elif defined(TARGET_RISCV64)
#elif defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64)
static const PCODE GPRegsLoadRoutines[] = {
(PCODE)Load_A0, (PCODE)Load_A0_A1, (PCODE)Load_A0_A1_A2, (PCODE)Load_A0_A1_A2_A3, (PCODE)Load_A0_A1_A2_A3_A4, (PCODE)Load_A0_A1_A2_A3_A4_A5, (PCODE)Load_A0_A1_A2_A3_A4_A5_A6, (PCODE)Load_A0_A1_A2_A3_A4_A5_A6_A7,
(PCODE)0, (PCODE)Load_A1, (PCODE)Load_A1_A2, (PCODE)Load_A1_A2_A3, (PCODE)Load_A1_A2_A3_A4, (PCODE)Load_A1_A2_A3_A4_A5, (PCODE)Load_A1_A2_A3_A4_A5_A6, (PCODE)Load_A1_A2_A3_A4_A5_A6_A7,
Expand Down Expand Up @@ -931,7 +931,7 @@ PCODE CallStubGenerator::GetGPRegRefRoutine(int r)
(PCODE)Store_Ref_X0, (PCODE)Store_Ref_X1, (PCODE)Store_Ref_X2, (PCODE)Store_Ref_X3,
(PCODE)Store_Ref_X4, (PCODE)Store_Ref_X5, (PCODE)Store_Ref_X6, (PCODE)Store_Ref_X7
};
#elif defined(TARGET_RISCV64)
#elif defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64)
static const PCODE GPRegsRefLoadRoutines[] = {
(PCODE)Load_Ref_A0, (PCODE)Load_Ref_A1, (PCODE)Load_Ref_A2, (PCODE)Load_Ref_A3,
(PCODE)Load_Ref_A4, (PCODE)Load_Ref_A5, (PCODE)Load_Ref_A6, (PCODE)Load_Ref_A7
Expand Down Expand Up @@ -1017,7 +1017,7 @@ PCODE CallStubGenerator::GetFPRegRangeRoutine(int x1, int x2)
(PCODE)0, (PCODE)0, (PCODE)0, (PCODE)0, (PCODE)0, (PCODE)0, (PCODE)Store_D6, (PCODE)Store_D6_D7,
(PCODE)0, (PCODE)0, (PCODE)0, (PCODE)0, (PCODE)0, (PCODE)0, (PCODE)0, (PCODE)Store_D7
};
#elif defined(TARGET_RISCV64)
#elif defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64)
static const PCODE FPRegsLoadRoutines[] = {
(PCODE)Load_FA0, (PCODE)Load_FA0_FA1, (PCODE)Load_FA0_FA1_FA2, (PCODE)Load_FA0_FA1_FA2_FA3, (PCODE)Load_FA0_FA1_FA2_FA3_FA4, (PCODE)Load_FA0_FA1_FA2_FA3_FA4_FA5, (PCODE)Load_FA0_FA1_FA2_FA3_FA4_FA5_FA6, (PCODE)Load_FA0_FA1_FA2_FA3_FA4_FA5_FA6_FA7,
(PCODE)0, (PCODE)Load_FA1, (PCODE)Load_FA1_FA2, (PCODE)Load_FA1_FA2_FA3, (PCODE)Load_FA1_FA2_FA3_FA4, (PCODE)Load_FA1_FA2_FA3_FA4_FA5, (PCODE)Load_FA1_FA2_FA3_FA4_FA5_FA6, (PCODE)Load_FA1_FA2_FA3_FA4_FA5_FA6_FA7,
Expand Down Expand Up @@ -1315,16 +1315,20 @@ extern "C" void InterpreterStubRet3Vector128();
extern "C" void InterpreterStubRet4Vector128();
#endif // TARGET_ARM64

#if defined(TARGET_RISCV64)
#if defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64)
extern "C" void CallJittedMethodRetFloat(PCODE *routines, int8_t*pArgs, int8_t*pRet, int totalStackSize, PTR_PTR_Object pContinuation);
extern "C" void CallJittedMethodRet2Float(PCODE *routines, int8_t*pArgs, int8_t*pRet, int totalStackSize, PTR_PTR_Object pContinuation);
extern "C" void CallJittedMethodRet2I8(PCODE *routines, int8_t*pArgs, int8_t*pRet, int totalStackSize, PTR_PTR_Object pContinuation);
extern "C" void CallJittedMethodRet2Double(PCODE *routines, int8_t*pArgs, int8_t*pRet, int totalStackSize, PTR_PTR_Object pContinuation);
extern "C" void CallJittedMethodRetFloatInt(PCODE *routines, int8_t*pArgs, int8_t*pRet, int totalStackSize, PTR_PTR_Object pContinuation);
extern "C" void CallJittedMethodRetIntFloat(PCODE *routines, int8_t*pArgs, int8_t*pRet, int totalStackSize, PTR_PTR_Object pContinuation);
extern "C" void InterpreterStubRetFloat();
extern "C" void InterpreterStubRet2Float();
extern "C" void InterpreterStubRet2I8();
extern "C" void InterpreterStubRet2Double();
extern "C" void InterpreterStubRetFloatInt();
extern "C" void InterpreterStubRetIntFloat();
#endif // TARGET_RISCV64
#endif // TARGET_RISCV64 || TARGET_LOONGARCH64

#define INVOKE_FUNCTION_PTR(functionPtrName) LOG2((LF2_INTERPRETER, LL_INFO10000, #functionPtrName "\n")); return functionPtrName

Expand Down Expand Up @@ -1432,7 +1436,11 @@ CallStubHeader::InvokeFunctionPtr CallStubGenerator::GetInvokeFunctionPtr(CallSt
INVOKE_FUNCTION_PTR(CallJittedMethodRetSwiftLowered);
#endif // TARGET_APPLE
#endif // TARGET_ARM64
#if defined(TARGET_RISCV64)
#if defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64)
case ReturnTypeFloat:
INVOKE_FUNCTION_PTR(CallJittedMethodRetFloat);
case ReturnType2Float:
INVOKE_FUNCTION_PTR(CallJittedMethodRet2Float);
case ReturnType2I8:
INVOKE_FUNCTION_PTR(CallJittedMethodRet2I8);
case ReturnType2Double:
Expand All @@ -1441,7 +1449,7 @@ CallStubHeader::InvokeFunctionPtr CallStubGenerator::GetInvokeFunctionPtr(CallSt
INVOKE_FUNCTION_PTR(CallJittedMethodRetFloatInt);
case ReturnTypeIntFloat:
INVOKE_FUNCTION_PTR(CallJittedMethodRetIntFloat);
#endif // TARGET_RISCV64
#endif // TARGET_RISCV64 || TARGET_LOONGARCH64
default:
_ASSERTE(!"Unexpected return type for interpreter stub");
return NULL; // This should never happen, but just in case.
Expand Down Expand Up @@ -1547,7 +1555,11 @@ PCODE CallStubGenerator::GetInterpreterReturnTypeHandler(CallStubGenerator::Retu
case ReturnType4Vector128:
RETURN_TYPE_HANDLER(InterpreterStubRet4Vector128);
#endif // TARGET_ARM64
#if defined(TARGET_RISCV64)
#if defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64)
case ReturnTypeFloat:
RETURN_TYPE_HANDLER(InterpreterStubRetFloat);
case ReturnType2Float:
RETURN_TYPE_HANDLER(InterpreterStubRet2Float);
case ReturnType2I8:
RETURN_TYPE_HANDLER(InterpreterStubRet2I8);
case ReturnType2Double:
Expand All @@ -1556,7 +1568,7 @@ PCODE CallStubGenerator::GetInterpreterReturnTypeHandler(CallStubGenerator::Retu
RETURN_TYPE_HANDLER(InterpreterStubRetFloatInt);
case ReturnTypeIntFloat:
RETURN_TYPE_HANDLER(InterpreterStubRetIntFloat);
#endif // TARGET_RISCV64
#endif // TARGET_RISCV64 || TARGET_LOONGARCH64
default:
_ASSERTE(!"Unexpected return type for interpreter stub");
return 0; // This should never happen, but just in case.
Expand Down Expand Up @@ -2665,9 +2677,9 @@ CallStubGenerator::ReturnType CallStubGenerator::GetReturnType(ArgIteratorType *
return ReturnTypeI8;
break;
case ELEMENT_TYPE_R4:
#if defined(TARGET_ARM64) || defined(TARGET_32BIT)
#if defined(TARGET_ARM64) || defined(TARGET_32BIT) || defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64)
return ReturnTypeFloat;
#endif // TARGET_ARM64 || TARGET_32BIT
#endif // TARGET_ARM64 || TARGET_32BIT || TARGET_RISCV64 || TARGET_LOONGARCH64
case ELEMENT_TYPE_R8:
return ReturnTypeDouble;
break;
Expand Down Expand Up @@ -2821,19 +2833,21 @@ CallStubGenerator::ReturnType CallStubGenerator::GetReturnType(ArgIteratorType *
_ASSERTE(!"The return types should be <= 8 bytes in size");
break;
}
#elif defined(TARGET_RISCV64)
#elif defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64)
{
FpStructInRegistersInfo info = pArgIt->GetReturnFpStructInRegistersInfo();
// RISC-V pass floating-point struct fields in FA registers
// RISC-V and LoongArch64 pass floating-point struct fields in FA/F registers.
// Preserve 32-bit float width where applicable to avoid reading/writing
// packed 4-byte fields via 8-byte helpers.
if ((info.flags & FpStruct::OnlyOne) != 0)
{
// Single field - could be float or int in single register
return ReturnTypeDouble; // Use Double routine for both float and double (NaN-boxed)
return (info.Size1st() == sizeof(float)) ? ReturnTypeFloat : ReturnTypeDouble;
}
else if ((info.flags & FpStruct::BothFloat) != 0)
{
// Two float/double fields
return ReturnType2Double;
return (info.Size1st() == sizeof(float) && info.Size2nd() == sizeof(float))
? ReturnType2Float
: ReturnType2Double;
}
else if ((info.flags & FpStruct::FloatInt) != 0)
{
Expand Down
6 changes: 4 additions & 2 deletions src/coreclr/vm/callstubgenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,14 @@ class CallStubGenerator
ReturnTypeSwiftLowered,
#endif // TARGET_APPLE
#endif // TARGET_ARM64
#if defined(TARGET_RISCV64)
#if defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64)
ReturnTypeFloat,
ReturnType2Float,
ReturnType2I8,
ReturnType2Double,
ReturnTypeFloatInt,
ReturnTypeIntFloat,
#endif // TARGET_RISCV64
#endif // TARGET_RISCV64 || TARGET_LOONGARCH64
};

enum class RoutineType
Expand Down
20 changes: 20 additions & 0 deletions src/coreclr/vm/loongarch64/asmconstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ ASMCONSTANTS_C_ASSERT(Thread__m_pFrame == offsetof(Thread, m_pFrame));
#define OFFSETOF__RuntimeThreadLocals__ee_alloc_context 0
ASMCONSTANTS_C_ASSERT(OFFSETOF__RuntimeThreadLocals__ee_alloc_context == offsetof(RuntimeThreadLocals, alloc_context));

#define OFFSETOF__ThreadLocalInfo__m_pThread 0
ASMCONSTANTS_C_ASSERT(OFFSETOF__ThreadLocalInfo__m_pThread == offsetof(ThreadLocalInfo, m_pThread));

#define OFFSETOF__ee_alloc_context__alloc_ptr 0x8
ASMCONSTANTS_C_ASSERT(OFFSETOF__ee_alloc_context__alloc_ptr == offsetof(ee_alloc_context, m_GCAllocContext) +
offsetof(gc_alloc_context, alloc_ptr));
Expand Down Expand Up @@ -219,6 +222,23 @@ ASMCONSTANTS_C_ASSERT(StubPrecodeData__Target == offsetof(StubPrecode
#define StubPrecodeData__SecretParam 0x00
ASMCONSTANTS_C_ASSERT(StubPrecodeData__SecretParam == offsetof(StubPrecodeData, SecretParam))

#ifdef FEATURE_INTERPRETER
#define OFFSETOF__InterpMethod__pCallStub 0x20
ASMCONSTANTS_C_ASSERT(OFFSETOF__InterpMethod__pCallStub == offsetof(InterpMethod, pCallStub))

#define OFFSETOF__Thread__m_pInterpThreadContext 0xB20
ASMCONSTANTS_C_ASSERT(OFFSETOF__Thread__m_pInterpThreadContext == offsetof(Thread, m_pInterpThreadContext))

#define OFFSETOF__InterpThreadContext__pStackPointer 0x10
ASMCONSTANTS_C_ASSERT(OFFSETOF__InterpThreadContext__pStackPointer == offsetof(InterpThreadContext, pStackPointer))

#define OFFSETOF__CallStubHeader__Routines 0x18
ASMCONSTANTS_C_ASSERT(OFFSETOF__CallStubHeader__Routines == offsetof(CallStubHeader, Routines))

#define SIZEOF__TransitionBlock 0xA0
ASMCONSTANTS_C_ASSERT(SIZEOF__TransitionBlock == sizeof(TransitionBlock))
#endif // FEATURE_INTERPRETER

#ifdef FEATURE_TIERED_COMPILATION
#define CallCountingStubData__RemainingCallCountCell 0x00
ASMCONSTANTS_C_ASSERT(CallCountingStubData__RemainingCallCountCell == offsetof(CallCountingStubData, RemainingCallCountCell))
Expand Down
Loading
Loading