diff --git a/docs/design/coreclr/botr/clr-abi.md b/docs/design/coreclr/botr/clr-abi.md index 65717698e421c..8be4d5b47ef68 100644 --- a/docs/design/coreclr/botr/clr-abi.md +++ b/docs/design/coreclr/botr/clr-abi.md @@ -26,6 +26,8 @@ Arm corporation ABI documentation (for ARM32 and ARM64) is [here](https://develo The Linux System V x86_64 ABI is documented in [System V Application Binary Interface / AMD64 Architecture Processor Supplement](https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-1.0.pdf), with document source material [here](https://gitlab.com/x86-psABIs/x86-64-ABI). +The LoongArch64 ABI documentation is [here](https://github.com/loongson/LoongArch-Documentation/blob/main/docs/LoongArch-ELF-ABI-EN.adoc) + # General Unwind/Frame Layout For all non-x86 platforms, all methods must have unwind information so the garbage collector (GC) can unwind them (unlike native code in which a leaf method may be omitted). diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index 4b52f6071eeab..28f4c880b62a1 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -316,6 +316,45 @@ struct SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR } }; +// StructFloadFieldInfoFlags: used on LoongArch64 architecture by `getLoongArch64PassStructInRegisterFlags` API +// to convey struct argument passing information. +// +// `STRUCT_NO_FLOAT_FIELD` means structs are not passed using the float register(s). +// +// Otherwise, and only for structs with no more than two fields and a total struct size no larger +// than two pointers: +// +// The lowest four bits denote the floating-point info: +// bit 0: `1` means there is only one float or double field within the struct. +// bit 1: `1` means only the first field is floating-point type. +// bit 2: `1` means only the second field is floating-point type. +// bit 3: `1` means the two fields are both floating-point type. +// The bits[5:4] denoting whether the field size is 8-bytes: +// bit 4: `1` means the first field's size is 8. +// bit 5: `1` means the second field's size is 8. +// +// Note that bit 0 and 3 cannot both be set. +enum StructFloatFieldInfoFlags +{ + STRUCT_NO_FLOAT_FIELD = 0x0, + STRUCT_FLOAT_FIELD_ONLY_ONE = 0x1, + STRUCT_FLOAT_FIELD_ONLY_TWO = 0x8, + STRUCT_FLOAT_FIELD_FIRST = 0x2, + STRUCT_FLOAT_FIELD_SECOND = 0x4, + STRUCT_FIRST_FIELD_SIZE_IS8 = 0x10, + STRUCT_SECOND_FIELD_SIZE_IS8 = 0x20, + + STRUCT_FIRST_FIELD_DOUBLE = (STRUCT_FLOAT_FIELD_FIRST | STRUCT_FIRST_FIELD_SIZE_IS8), + STRUCT_SECOND_FIELD_DOUBLE = (STRUCT_FLOAT_FIELD_SECOND | STRUCT_SECOND_FIELD_SIZE_IS8), + STRUCT_FIELD_TWO_DOUBLES = (STRUCT_FIRST_FIELD_SIZE_IS8 | STRUCT_SECOND_FIELD_SIZE_IS8 | STRUCT_FLOAT_FIELD_ONLY_TWO), + + STRUCT_MERGE_FIRST_SECOND = (STRUCT_FLOAT_FIELD_FIRST | STRUCT_FLOAT_FIELD_ONLY_TWO), + STRUCT_MERGE_FIRST_SECOND_8 = (STRUCT_FLOAT_FIELD_FIRST | STRUCT_FLOAT_FIELD_ONLY_TWO | STRUCT_SECOND_FIELD_SIZE_IS8), + + STRUCT_HAS_FLOAT_FIELDS_MASK = (STRUCT_FLOAT_FIELD_FIRST | STRUCT_FLOAT_FIELD_SECOND | STRUCT_FLOAT_FIELD_ONLY_TWO | STRUCT_FLOAT_FIELD_ONLY_ONE), + STRUCT_HAS_8BYTES_FIELDS_MASK = (STRUCT_FIRST_FIELD_SIZE_IS8 | STRUCT_SECOND_FIELD_SIZE_IS8), +}; + #include "corinfoinstructionset.h" // CorInfoHelpFunc defines the set of helpers (accessed via the ICorDynamicInfo::getHelperFtn()) @@ -2843,6 +2882,7 @@ class ICorStaticInfo /* OUT */ SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr ) = 0; + virtual uint32_t getLoongArch64PassStructInRegisterFlags(CORINFO_CLASS_HANDLE cls) = 0; }; /***************************************************************************** diff --git a/src/coreclr/inc/icorjitinfoimpl_generated.h b/src/coreclr/inc/icorjitinfoimpl_generated.h index 132707a4ef485..ace6a7892207f 100644 --- a/src/coreclr/inc/icorjitinfoimpl_generated.h +++ b/src/coreclr/inc/icorjitinfoimpl_generated.h @@ -480,6 +480,9 @@ bool getSystemVAmd64PassStructInRegisterDescriptor( CORINFO_CLASS_HANDLE structHnd, SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr) override; +uint32_t getLoongArch64PassStructInRegisterFlags( + CORINFO_CLASS_HANDLE structHnd) override; + uint32_t getThreadTLSIndex( void** ppIndirection) override; diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index c8760ad9999d8..303f97b6e7779 100644 --- a/src/coreclr/inc/jiteeversionguid.h +++ b/src/coreclr/inc/jiteeversionguid.h @@ -43,12 +43,12 @@ typedef const GUID *LPCGUID; #define GUID_DEFINED #endif // !GUID_DEFINED -constexpr GUID JITEEVersionIdentifier = { /* e6a73797-0cbe-4cf8-b4ad-724a25466211 */ - 0xe6a73797, - 0x0cbe, - 0x4cf8, - {0xb4, 0xad, 0x72, 0x4a, 0x25, 0x46, 0x62, 0x11} -}; +constexpr GUID JITEEVersionIdentifier = { /* 80a6aaf7-7fb3-44b2-8fe5-95fd47308798 */ + 0x80a6aaf7, + 0x7fb3, + 0x44b2, + {0x8f, 0xe5, 0x95, 0xfd, 0x47, 0x30, 0x87, 0x98} + }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// // diff --git a/src/coreclr/jit/ICorJitInfo_API_names.h b/src/coreclr/jit/ICorJitInfo_API_names.h index 36a7f89f4718c..fec05d5c398f1 100644 --- a/src/coreclr/jit/ICorJitInfo_API_names.h +++ b/src/coreclr/jit/ICorJitInfo_API_names.h @@ -122,6 +122,7 @@ DEF_CLR_API(getMethodNameFromMetadata) DEF_CLR_API(getMethodHash) DEF_CLR_API(findNameOfToken) DEF_CLR_API(getSystemVAmd64PassStructInRegisterDescriptor) +DEF_CLR_API(getLoongArch64PassStructInRegisterFlags) DEF_CLR_API(getThreadTLSIndex) DEF_CLR_API(getInlinedCallFrameVptr) DEF_CLR_API(getAddrOfCaptureThreadGlobal) diff --git a/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp b/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp index 2cd1c0d4235d9..fea393b10635d 100644 --- a/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp +++ b/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp @@ -1154,6 +1154,15 @@ bool WrapICorJitInfo::getSystemVAmd64PassStructInRegisterDescriptor( return temp; } +uint32_t WrapICorJitInfo::getLoongArch64PassStructInRegisterFlags( + CORINFO_CLASS_HANDLE structHnd) +{ + API_ENTER(getLoongArch64PassStructInRegisterFlags); + uint32_t temp = wrapHnd->getLoongArch64PassStructInRegisterFlags(structHnd); + API_LEAVE(getLoongArch64PassStructInRegisterFlags); + return temp; +} + uint32_t WrapICorJitInfo::getThreadTLSIndex( void** ppIndirection) { diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs b/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs index 858afde75164e..ae02a31a463b7 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs @@ -1757,6 +1757,21 @@ static byte _getSystemVAmd64PassStructInRegisterDescriptor(IntPtr thisHandle, In } } + [UnmanagedCallersOnly] + static uint _getLoongArch64PassStructInRegisterFlags(IntPtr thisHandle, IntPtr* ppException, CORINFO_CLASS_STRUCT_* structHnd) + { + var _this = GetThis(thisHandle); + try + { + return _this.getLoongArch64PassStructInRegisterFlags(structHnd); + } + catch (Exception ex) + { + *ppException = _this.AllocException(ex); + return default; + } + } + [UnmanagedCallersOnly] static uint _getThreadTLSIndex(IntPtr thisHandle, IntPtr* ppException, void** ppIndirection) { @@ -2552,7 +2567,7 @@ static byte _doesFieldBelongToClass(IntPtr thisHandle, IntPtr* ppException, CORI static IntPtr GetUnmanagedCallbacks() { - void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 172); + void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 173); callbacks[0] = (delegate* unmanaged)&_isIntrinsic; callbacks[1] = (delegate* unmanaged)&_getMethodAttribs; @@ -2672,60 +2687,61 @@ static IntPtr GetUnmanagedCallbacks() callbacks[115] = (delegate* unmanaged)&_getMethodHash; callbacks[116] = (delegate* unmanaged)&_findNameOfToken; callbacks[117] = (delegate* unmanaged)&_getSystemVAmd64PassStructInRegisterDescriptor; - callbacks[118] = (delegate* unmanaged)&_getThreadTLSIndex; - callbacks[119] = (delegate* unmanaged)&_getInlinedCallFrameVptr; - callbacks[120] = (delegate* unmanaged)&_getAddrOfCaptureThreadGlobal; - callbacks[121] = (delegate* unmanaged)&_getHelperFtn; - callbacks[122] = (delegate* unmanaged)&_getFunctionEntryPoint; - callbacks[123] = (delegate* unmanaged)&_getFunctionFixedEntryPoint; - callbacks[124] = (delegate* unmanaged)&_getMethodSync; - callbacks[125] = (delegate* unmanaged)&_getLazyStringLiteralHelper; - callbacks[126] = (delegate* unmanaged)&_embedModuleHandle; - callbacks[127] = (delegate* unmanaged)&_embedClassHandle; - callbacks[128] = (delegate* unmanaged)&_embedMethodHandle; - callbacks[129] = (delegate* unmanaged)&_embedFieldHandle; - callbacks[130] = (delegate* unmanaged)&_embedGenericHandle; - callbacks[131] = (delegate* unmanaged)&_getLocationOfThisType; - callbacks[132] = (delegate* unmanaged)&_getAddressOfPInvokeTarget; - callbacks[133] = (delegate* unmanaged)&_GetCookieForPInvokeCalliSig; - callbacks[134] = (delegate* unmanaged)&_canGetCookieForPInvokeCalliSig; - callbacks[135] = (delegate* unmanaged)&_getJustMyCodeHandle; - callbacks[136] = (delegate* unmanaged)&_GetProfilingHandle; - callbacks[137] = (delegate* unmanaged)&_getCallInfo; - callbacks[138] = (delegate* unmanaged)&_canAccessFamily; - callbacks[139] = (delegate* unmanaged)&_isRIDClassDomainID; - callbacks[140] = (delegate* unmanaged)&_getClassDomainID; - callbacks[141] = (delegate* unmanaged)&_getFieldAddress; - callbacks[142] = (delegate* unmanaged)&_getStaticFieldCurrentClass; - callbacks[143] = (delegate* unmanaged)&_getVarArgsHandle; - callbacks[144] = (delegate* unmanaged)&_canGetVarArgsHandle; - callbacks[145] = (delegate* unmanaged)&_constructStringLiteral; - callbacks[146] = (delegate* unmanaged)&_emptyStringLiteral; - callbacks[147] = (delegate* unmanaged)&_getFieldThreadLocalStoreID; - callbacks[148] = (delegate* unmanaged)&_addActiveDependency; - callbacks[149] = (delegate* unmanaged)&_GetDelegateCtor; - callbacks[150] = (delegate* unmanaged)&_MethodCompileComplete; - callbacks[151] = (delegate* unmanaged)&_getTailCallHelpers; - callbacks[152] = (delegate* unmanaged)&_convertPInvokeCalliToCall; - callbacks[153] = (delegate* unmanaged)&_notifyInstructionSetUsage; - callbacks[154] = (delegate* unmanaged)&_updateEntryPointForTailCall; - callbacks[155] = (delegate* unmanaged)&_allocMem; - callbacks[156] = (delegate* unmanaged)&_reserveUnwindInfo; - callbacks[157] = (delegate* unmanaged)&_allocUnwindInfo; - callbacks[158] = (delegate* unmanaged)&_allocGCInfo; - callbacks[159] = (delegate* unmanaged)&_setEHcount; - callbacks[160] = (delegate* unmanaged)&_setEHinfo; - callbacks[161] = (delegate* unmanaged)&_logMsg; - callbacks[162] = (delegate* unmanaged)&_doAssert; - callbacks[163] = (delegate* unmanaged)&_reportFatalError; - callbacks[164] = (delegate* unmanaged)&_getPgoInstrumentationResults; - callbacks[165] = (delegate* unmanaged)&_allocPgoInstrumentationBySchema; - callbacks[166] = (delegate* unmanaged)&_recordCallSite; - callbacks[167] = (delegate* unmanaged)&_recordRelocation; - callbacks[168] = (delegate* unmanaged)&_getRelocTypeHint; - callbacks[169] = (delegate* unmanaged)&_getExpectedTargetArchitecture; - callbacks[170] = (delegate* unmanaged)&_getJitFlags; - callbacks[171] = (delegate* unmanaged)&_doesFieldBelongToClass; + callbacks[118] = (delegate* unmanaged)&_getLoongArch64PassStructInRegisterFlags; + callbacks[119] = (delegate* unmanaged)&_getThreadTLSIndex; + callbacks[120] = (delegate* unmanaged)&_getInlinedCallFrameVptr; + callbacks[121] = (delegate* unmanaged)&_getAddrOfCaptureThreadGlobal; + callbacks[122] = (delegate* unmanaged)&_getHelperFtn; + callbacks[123] = (delegate* unmanaged)&_getFunctionEntryPoint; + callbacks[124] = (delegate* unmanaged)&_getFunctionFixedEntryPoint; + callbacks[125] = (delegate* unmanaged)&_getMethodSync; + callbacks[126] = (delegate* unmanaged)&_getLazyStringLiteralHelper; + callbacks[127] = (delegate* unmanaged)&_embedModuleHandle; + callbacks[128] = (delegate* unmanaged)&_embedClassHandle; + callbacks[129] = (delegate* unmanaged)&_embedMethodHandle; + callbacks[130] = (delegate* unmanaged)&_embedFieldHandle; + callbacks[131] = (delegate* unmanaged)&_embedGenericHandle; + callbacks[132] = (delegate* unmanaged)&_getLocationOfThisType; + callbacks[133] = (delegate* unmanaged)&_getAddressOfPInvokeTarget; + callbacks[134] = (delegate* unmanaged)&_GetCookieForPInvokeCalliSig; + callbacks[135] = (delegate* unmanaged)&_canGetCookieForPInvokeCalliSig; + callbacks[136] = (delegate* unmanaged)&_getJustMyCodeHandle; + callbacks[137] = (delegate* unmanaged)&_GetProfilingHandle; + callbacks[138] = (delegate* unmanaged)&_getCallInfo; + callbacks[139] = (delegate* unmanaged)&_canAccessFamily; + callbacks[140] = (delegate* unmanaged)&_isRIDClassDomainID; + callbacks[141] = (delegate* unmanaged)&_getClassDomainID; + callbacks[142] = (delegate* unmanaged)&_getFieldAddress; + callbacks[143] = (delegate* unmanaged)&_getStaticFieldCurrentClass; + callbacks[144] = (delegate* unmanaged)&_getVarArgsHandle; + callbacks[145] = (delegate* unmanaged)&_canGetVarArgsHandle; + callbacks[146] = (delegate* unmanaged)&_constructStringLiteral; + callbacks[147] = (delegate* unmanaged)&_emptyStringLiteral; + callbacks[148] = (delegate* unmanaged)&_getFieldThreadLocalStoreID; + callbacks[149] = (delegate* unmanaged)&_addActiveDependency; + callbacks[150] = (delegate* unmanaged)&_GetDelegateCtor; + callbacks[151] = (delegate* unmanaged)&_MethodCompileComplete; + callbacks[152] = (delegate* unmanaged)&_getTailCallHelpers; + callbacks[153] = (delegate* unmanaged)&_convertPInvokeCalliToCall; + callbacks[154] = (delegate* unmanaged)&_notifyInstructionSetUsage; + callbacks[155] = (delegate* unmanaged)&_updateEntryPointForTailCall; + callbacks[156] = (delegate* unmanaged)&_allocMem; + callbacks[157] = (delegate* unmanaged)&_reserveUnwindInfo; + callbacks[158] = (delegate* unmanaged)&_allocUnwindInfo; + callbacks[159] = (delegate* unmanaged)&_allocGCInfo; + callbacks[160] = (delegate* unmanaged)&_setEHcount; + callbacks[161] = (delegate* unmanaged)&_setEHinfo; + callbacks[162] = (delegate* unmanaged)&_logMsg; + callbacks[163] = (delegate* unmanaged)&_doAssert; + callbacks[164] = (delegate* unmanaged)&_reportFatalError; + callbacks[165] = (delegate* unmanaged)&_getPgoInstrumentationResults; + callbacks[166] = (delegate* unmanaged)&_allocPgoInstrumentationBySchema; + callbacks[167] = (delegate* unmanaged)&_recordCallSite; + callbacks[168] = (delegate* unmanaged)&_recordRelocation; + callbacks[169] = (delegate* unmanaged)&_getRelocTypeHint; + callbacks[170] = (delegate* unmanaged)&_getExpectedTargetArchitecture; + callbacks[171] = (delegate* unmanaged)&_getJitFlags; + callbacks[172] = (delegate* unmanaged)&_doesFieldBelongToClass; return (IntPtr)callbacks; } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 3d6640adb458b..28c20a50efb77 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -2936,6 +2936,11 @@ private CorInfoTypeWithMod getArgType(CORINFO_SIG_INFO* sig, CORINFO_ARG_LIST_ST } } + private uint getLoongArch64PassStructInRegisterFlags(CORINFO_CLASS_STRUCT_* cls) + { + throw new NotImplementedException("For LoongArch64, would be implemented later"); + } + private CORINFO_CLASS_STRUCT_* getArgClass(CORINFO_SIG_INFO* sig, CORINFO_ARG_LIST_STRUCT_* args) { int index = (int)args; diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index 7cccae04c4151..86b32b7f85b5f 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -271,6 +271,7 @@ FUNCTIONS unsigned getMethodHash(CORINFO_METHOD_HANDLE ftn); size_t findNameOfToken(CORINFO_MODULE_HANDLE moduleHandle,mdToken token, char * szFQName,size_t FQNameCapacity); bool getSystemVAmd64PassStructInRegisterDescriptor(CORINFO_CLASS_HANDLE structHnd, SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr); + uint32_t getLoongArch64PassStructInRegisterFlags(CORINFO_CLASS_HANDLE structHnd); uint32_t getThreadTLSIndex(void **ppIndirection); const void * getInlinedCallFrameVptr(void **ppIndirection); int32_t * getAddrOfCaptureThreadGlobal(void **ppIndirection); diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface.h b/src/coreclr/tools/aot/jitinterface/jitinterface.h index 9f802bdb46183..3b0f84d5b1d51 100644 --- a/src/coreclr/tools/aot/jitinterface/jitinterface.h +++ b/src/coreclr/tools/aot/jitinterface/jitinterface.h @@ -129,6 +129,7 @@ struct JitInterfaceCallbacks unsigned (* getMethodHash)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftn); size_t (* findNameOfToken)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_MODULE_HANDLE moduleHandle, unsigned int token, char* szFQName, size_t FQNameCapacity); bool (* getSystemVAmd64PassStructInRegisterDescriptor)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE structHnd, SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr); + uint32_t (* getLoongArch64PassStructInRegisterFlags)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE structHnd); uint32_t (* getThreadTLSIndex)(void * thisHandle, CorInfoExceptionClass** ppException, void** ppIndirection); const void* (* getInlinedCallFrameVptr)(void * thisHandle, CorInfoExceptionClass** ppException, void** ppIndirection); int32_t* (* getAddrOfCaptureThreadGlobal)(void * thisHandle, CorInfoExceptionClass** ppException, void** ppIndirection); @@ -1322,6 +1323,15 @@ class JitInterfaceWrapper : public ICorJitInfo return temp; } + virtual uint32_t getLoongArch64PassStructInRegisterFlags( + CORINFO_CLASS_HANDLE structHnd) +{ + CorInfoExceptionClass* pException = nullptr; + uint32_t temp = _callbacks->getLoongArch64PassStructInRegisterFlags(_thisHandle, &pException, structHnd); + if (pException != nullptr) throw pException; + return temp; +} + virtual uint32_t getThreadTLSIndex( void** ppIndirection) { diff --git a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h index aae223f728562..4c0ebcc086d12 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h @@ -127,6 +127,7 @@ LWM(GetExpectedTargetArchitecture, DWORD, DWORD) LWM(GetSharedCCtorHelper, DWORDLONG, DWORD) LWM(GetStringConfigValue, DWORD, DWORD) LWM(GetSystemVAmd64PassStructInRegisterDescriptor, DWORDLONG, Agnostic_GetSystemVAmd64PassStructInRegisterDescriptor) +LWM(GetLoongArch64PassStructInRegisterFlags, DWORDLONG, DWORD) LWM(GetTailCallHelpers, Agnostic_GetTailCallHelpers, Agnostic_CORINFO_TAILCALL_HELPERS) LWM(UpdateEntryPointForTailCall, Agnostic_CORINFO_CONST_LOOKUP, Agnostic_CORINFO_CONST_LOOKUP) LWM(GetThreadTLSIndex, DWORD, DLD) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index 21526c49fb5f4..b28b8d736e096 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -2661,6 +2661,7 @@ void MethodContext::recGetArgType(CORINFO_SIG_INFO* sig, GetArgType->Add(key, value); DEBUG_REC(dmpGetArgType(key, value)); } + void MethodContext::dmpGetArgType(const Agnostic_GetArgType_Key& key, const Agnostic_GetArgType_Value& value) { printf("GetArgType key flg-%08X na-%u %s %s msig-%016llX scp-%016llX arg-%016llX", @@ -2670,6 +2671,7 @@ void MethodContext::dmpGetArgType(const Agnostic_GetArgType_Key& key, const Agno key.methodSignature, key.scope, key.args); printf(", value result(cit)-%u(%s) vcType-%016llX excp-%08X", value.result, toString((CorInfoTypeWithMod)value.result), value.vcTypeRet, value.exceptionCode); } + CorInfoTypeWithMod MethodContext::repGetArgType(CORINFO_SIG_INFO* sig, CORINFO_ARG_LIST_HANDLE args, CORINFO_CLASS_HANDLE* vcTypeRet, @@ -6120,6 +6122,31 @@ bool MethodContext::repGetSystemVAmd64PassStructInRegisterDescriptor( return value.result ? true : false; } +void MethodContext::recGetLoongArch64PassStructInRegisterFlags(CORINFO_CLASS_HANDLE structHnd, DWORD value) +{ + if (GetLoongArch64PassStructInRegisterFlags == nullptr) + GetLoongArch64PassStructInRegisterFlags = new LightWeightMap(); + + DWORDLONG key = CastHandle(structHnd); + + GetLoongArch64PassStructInRegisterFlags->Add(key, value); + DEBUG_REC(dmpGetLoongArch64PassStructInRegisterFlags(key, value)); +} + +void MethodContext::dmpGetLoongArch64PassStructInRegisterFlags(DWORDLONG key, DWORD value) +{ + printf("GetLoongArch64PassStructInRegisterFlags key %016llX value-%08X", key, value); +} + +DWORD MethodContext::repGetLoongArch64PassStructInRegisterFlags(CORINFO_CLASS_HANDLE structHnd) +{ + DWORDLONG key = CastHandle(structHnd); + + DWORD value = GetLoongArch64PassStructInRegisterFlags->Get(key); + DEBUG_REP(dmpGetLoongArch64PassStructInRegisterFlags(key, value)); + return value; +} + void MethodContext::recGetRelocTypeHint(void* target, WORD result) { if (GetRelocTypeHint == nullptr) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h index dc2e733e343fe..4c16c5186c359 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h @@ -751,6 +751,10 @@ class MethodContext bool repGetSystemVAmd64PassStructInRegisterDescriptor( CORINFO_CLASS_HANDLE structHnd, SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr); + void recGetLoongArch64PassStructInRegisterFlags(CORINFO_CLASS_HANDLE structHnd, DWORD value); + void dmpGetLoongArch64PassStructInRegisterFlags(DWORDLONG key, DWORD value); + DWORD repGetLoongArch64PassStructInRegisterFlags(CORINFO_CLASS_HANDLE structHnd); + void recGetRelocTypeHint(void* target, WORD result); void dmpGetRelocTypeHint(DWORDLONG key, DWORD value); WORD repGetRelocTypeHint(void* target); @@ -1095,6 +1099,7 @@ enum mcPackets Packet_GetAssemblyName = 191, Packet_IsIntrinsic = 192, Packet_UpdateEntryPointForTailCall = 193, + Packet_GetLoongArch64PassStructInRegisterFlags = 194, }; void SetDebugDumpVariables(); diff --git a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp index f347a616f96f4..0dbbc41b32fc8 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -1385,6 +1385,14 @@ bool interceptor_ICJI::getSystemVAmd64PassStructInRegisterDescriptor( return result; } +uint32_t interceptor_ICJI::getLoongArch64PassStructInRegisterFlags(CORINFO_CLASS_HANDLE structHnd) +{ + mc->cr->AddCall("getLoongArch64PassStructInRegisterFlags"); + uint32_t temp = original_ICorJitInfo->getLoongArch64PassStructInRegisterFlags(structHnd); + mc->recGetLoongArch64PassStructInRegisterFlags(structHnd, temp); + return temp; +} + // Stuff on ICorDynamicInfo uint32_t interceptor_ICJI::getThreadTLSIndex(void** ppIndirection) { diff --git a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp index 66f792968885d..cdedca095f4d4 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp @@ -943,6 +943,13 @@ bool interceptor_ICJI::getSystemVAmd64PassStructInRegisterDescriptor( return original_ICorJitInfo->getSystemVAmd64PassStructInRegisterDescriptor(structHnd, structPassInRegDescPtr); } +uint32_t interceptor_ICJI::getLoongArch64PassStructInRegisterFlags( + CORINFO_CLASS_HANDLE structHnd) +{ + mcs->AddCall("getLoongArch64PassStructInRegisterFlags"); + return original_ICorJitInfo->getLoongArch64PassStructInRegisterFlags(structHnd); +} + uint32_t interceptor_ICJI::getThreadTLSIndex( void** ppIndirection) { diff --git a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp index cd38c2c775939..1222ab264f526 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp @@ -825,6 +825,12 @@ bool interceptor_ICJI::getSystemVAmd64PassStructInRegisterDescriptor( return original_ICorJitInfo->getSystemVAmd64PassStructInRegisterDescriptor(structHnd, structPassInRegDescPtr); } +uint32_t interceptor_ICJI::getLoongArch64PassStructInRegisterFlags( + CORINFO_CLASS_HANDLE structHnd) +{ + return original_ICorJitInfo->getLoongArch64PassStructInRegisterFlags(structHnd); +} + uint32_t interceptor_ICJI::getThreadTLSIndex( void** ppIndirection) { diff --git a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp index d90f0b5e09706..f92a9cbd98fe7 100644 --- a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp @@ -1227,6 +1227,12 @@ bool MyICJI::getSystemVAmd64PassStructInRegisterDescriptor( return jitInstance->mc->repGetSystemVAmd64PassStructInRegisterDescriptor(structHnd, structPassInRegDescPtr); } +uint32_t MyICJI::getLoongArch64PassStructInRegisterFlags(CORINFO_CLASS_HANDLE structHnd) +{ + jitInstance->mc->cr->AddCall("getLoongArch64PassStructInRegisterFlags"); + return jitInstance->mc->repGetLoongArch64PassStructInRegisterFlags(structHnd); +} + // Stuff on ICorDynamicInfo uint32_t MyICJI::getThreadTLSIndex(void** ppIndirection) { diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 69a0abdfcb1ef..c994329f9684a 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -9279,6 +9279,456 @@ CorInfoTypeWithMod CEEInfo::getArgType ( return result; } +// Now the implementation is only focused on the float fields info, +// while a struct-arg has no more than two fields and total size is no larger than two-pointer-size. +// These depends on the platform's ABI rules. +// +// The returned value's encoding details how a struct argument uses float registers: +// see the enum `StructFloatFieldInfoFlags`. +uint32_t CEEInfo::getLoongArch64PassStructInRegisterFlags(CORINFO_CLASS_HANDLE cls) +{ + CONTRACTL { + NOTHROW; + GC_NOTRIGGER; + MODE_PREEMPTIVE; + } CONTRACTL_END; + + JIT_TO_EE_TRANSITION_LEAF(); + + TypeHandle th(cls); + + bool useNativeLayout = false; + uint32_t size = STRUCT_NO_FLOAT_FIELD; + MethodTable* pMethodTable = nullptr; + + if (!th.IsTypeDesc()) + { + pMethodTable = th.AsMethodTable(); + if (pMethodTable->HasLayout()) + useNativeLayout = true; + else if (th.GetSize() <= 16 /*MAX_PASS_MULTIREG_BYTES*/) + { + DWORD numIntroducedFields = pMethodTable->GetNumIntroducedInstanceFields(); + + if (numIntroducedFields == 1) + { + FieldDesc *pFieldStart = pMethodTable->GetApproxFieldDescListRaw(); + + CorElementType fieldType = pFieldStart[0].GetFieldType(); + + if (CorTypeInfo::IsPrimitiveType_NoThrow(fieldType)) + { + if ((fieldType == ELEMENT_TYPE_R4) || (fieldType == ELEMENT_TYPE_R8)) + size = STRUCT_FLOAT_FIELD_ONLY_ONE; + } + else if (fieldType == ELEMENT_TYPE_VALUETYPE) + { + pMethodTable = pFieldStart->GetFieldTypeHandleThrowing().GetMethodTable(); + if (pMethodTable->GetNumIntroducedInstanceFields() == 1) + { + size = getLoongArch64PassStructInRegisterFlags((CORINFO_CLASS_HANDLE)pMethodTable); + } + else if (pMethodTable->GetNumIntroducedInstanceFields() == 2) + { + size = getLoongArch64PassStructInRegisterFlags((CORINFO_CLASS_HANDLE)pMethodTable); + } + } + } + else if (numIntroducedFields == 2) + { + FieldDesc *pFieldStart = pMethodTable->GetApproxFieldDescListRaw(); + + CorElementType fieldType = pFieldStart[0].GetFieldType(); + if (CorTypeInfo::IsPrimitiveType_NoThrow(fieldType)) + { + if (fieldType == ELEMENT_TYPE_R4) + size = STRUCT_FLOAT_FIELD_FIRST; + else if (fieldType == ELEMENT_TYPE_R8) + size = STRUCT_FIRST_FIELD_DOUBLE; + else if (pFieldStart[0].GetSize() == 8) + size = STRUCT_FIRST_FIELD_SIZE_IS8; + + } + else if (fieldType == ELEMENT_TYPE_VALUETYPE) + { + pMethodTable = pFieldStart->GetFieldTypeHandleThrowing().GetMethodTable(); + if (pMethodTable->GetNumIntroducedInstanceFields() == 1) + { + size = getLoongArch64PassStructInRegisterFlags((CORINFO_CLASS_HANDLE)pMethodTable); + if (size == STRUCT_FLOAT_FIELD_ONLY_ONE) + { + size = pFieldStart[0].GetSize() == 8 ? STRUCT_FIRST_FIELD_DOUBLE : STRUCT_FLOAT_FIELD_FIRST; + } + else if (size == STRUCT_NO_FLOAT_FIELD) + { + size = pFieldStart[0].GetSize() == 8 ? STRUCT_FIRST_FIELD_SIZE_IS8: 0; + } + else + { + size = STRUCT_NO_FLOAT_FIELD; + goto _End_arg; + } + } + else + { + size = STRUCT_NO_FLOAT_FIELD; + goto _End_arg; + } + } + else if (pFieldStart[0].GetSize() == 8) + size = STRUCT_FIRST_FIELD_SIZE_IS8; + + fieldType = pFieldStart[1].GetFieldType(); + if (CorTypeInfo::IsPrimitiveType_NoThrow(fieldType)) + { + if (fieldType == ELEMENT_TYPE_R4) + size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND) : (size | STRUCT_FLOAT_FIELD_SECOND); + else if (fieldType == ELEMENT_TYPE_R8) + size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND_8) : (size | STRUCT_SECOND_FIELD_DOUBLE); + else if (pFieldStart[1].GetSize() == 8) + size |= STRUCT_SECOND_FIELD_SIZE_IS8; + } + else if (fieldType == ELEMENT_TYPE_VALUETYPE) + { + pMethodTable = pFieldStart[1].GetFieldTypeHandleThrowing().GetMethodTable(); + if (pMethodTable->GetNumIntroducedInstanceFields() == 1) + { + DWORD size2 = getLoongArch64PassStructInRegisterFlags((CORINFO_CLASS_HANDLE)pMethodTable); + if (size2 == STRUCT_FLOAT_FIELD_ONLY_ONE) + { + if (pFieldStart[1].GetSize() == 8) + size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND_8) : (size | STRUCT_SECOND_FIELD_DOUBLE); + else + size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND) : (size | STRUCT_FLOAT_FIELD_SECOND); + } + else if (size2 == 0) + { + size |= pFieldStart[1].GetSize() == 8 ? STRUCT_SECOND_FIELD_SIZE_IS8 : 0; + } + else + { + size = STRUCT_NO_FLOAT_FIELD; + goto _End_arg; + } + } + else + { + size = STRUCT_NO_FLOAT_FIELD; + goto _End_arg; + } + } + else if (pFieldStart[1].GetSize() == 8) + size |= STRUCT_SECOND_FIELD_SIZE_IS8; + } + goto _End_arg; + } + } + else + { + _ASSERTE(th.IsNativeValueType()); + + useNativeLayout = true; + pMethodTable = th.AsNativeValueType(); + } + _ASSERTE(pMethodTable != nullptr); + + if (useNativeLayout) + { + if (th.GetSize() <= 16 /*MAX_PASS_MULTIREG_BYTES*/) + { + DWORD numIntroducedFields = pMethodTable->GetNumIntroducedInstanceFields(); + FieldDesc *pFieldStart = nullptr; + + if (numIntroducedFields == 1) + { + pFieldStart = pMethodTable->GetApproxFieldDescListRaw(); + + CorElementType fieldType = pFieldStart->GetFieldType(); + + bool isFixedBuffer = (CorTypeInfo::IsPrimitiveType_NoThrow(fieldType) + || fieldType == ELEMENT_TYPE_VALUETYPE) + && (pFieldStart->GetOffset() == 0) + && pMethodTable->HasLayout() + && (pMethodTable->GetNumInstanceFieldBytes() % pFieldStart->GetSize() == 0); + + if (isFixedBuffer) + { + numIntroducedFields = pMethodTable->GetNumInstanceFieldBytes() / pFieldStart->GetSize(); + if (numIntroducedFields > 2) + goto _End_arg; + if (fieldType == ELEMENT_TYPE_R4) + { + if (numIntroducedFields == 1) + size = STRUCT_FLOAT_FIELD_ONLY_ONE; + else if (numIntroducedFields == 2) + size = STRUCT_FLOAT_FIELD_ONLY_TWO; + goto _End_arg; + } + else if (fieldType == ELEMENT_TYPE_R8) + { + if (numIntroducedFields == 1) + size = STRUCT_FLOAT_FIELD_ONLY_ONE; + else if (numIntroducedFields == 2) + size = STRUCT_FIELD_TWO_DOUBLES; + goto _End_arg; + } + } + + if (CorTypeInfo::IsPrimitiveType_NoThrow(fieldType)) + { + if ((fieldType == ELEMENT_TYPE_R4) || (fieldType == ELEMENT_TYPE_R8)) + size = STRUCT_FLOAT_FIELD_ONLY_ONE; + } + else if (fieldType == ELEMENT_TYPE_VALUETYPE) + { + const NativeFieldDescriptor *pNativeFieldDescs = pMethodTable->GetNativeLayoutInfo()->GetNativeFieldDescriptors(); + if (pNativeFieldDescs->GetCategory() == NativeFieldCategory::NESTED) + { + size = getLoongArch64PassStructInRegisterFlags((CORINFO_CLASS_HANDLE)pNativeFieldDescs->GetNestedNativeMethodTable()); + return size; + } + else if (pNativeFieldDescs->GetCategory() == NativeFieldCategory::FLOAT) + { + if (pNativeFieldDescs->NativeSize() == 4) + { + size = STRUCT_FLOAT_FIELD_ONLY_ONE; + } + else if (pNativeFieldDescs->NativeSize() == 8) + { + size = STRUCT_FLOAT_FIELD_ONLY_ONE; + } + else + { + UNREACHABLE_MSG("Invalid NativeFieldCategory.----LoongArch64----"); + } + } + else + { + pMethodTable = pNativeFieldDescs->GetNestedNativeMethodTable(); + if (pNativeFieldDescs->GetNumElements() == 1) + { + size = getLoongArch64PassStructInRegisterFlags((CORINFO_CLASS_HANDLE)pMethodTable); + } + else if (pNativeFieldDescs->GetNumElements() == 2) + { + size = getLoongArch64PassStructInRegisterFlags((CORINFO_CLASS_HANDLE)pMethodTable); + } + } + } + } + else if (numIntroducedFields == 2) + { + pFieldStart = pMethodTable->GetApproxFieldDescListRaw(); + + if (pFieldStart->GetOffset() || !pFieldStart[1].GetOffset() || (pFieldStart[0].GetSize() > pFieldStart[1].GetOffset())) + { + goto _End_arg; + } + + CorElementType fieldType = pFieldStart[0].GetFieldType(); + if (CorTypeInfo::IsPrimitiveType_NoThrow(fieldType)) + { + if (fieldType == ELEMENT_TYPE_R4) + size = STRUCT_FLOAT_FIELD_FIRST; + else if (fieldType == ELEMENT_TYPE_R8) + size = STRUCT_FIRST_FIELD_DOUBLE; + else if (pFieldStart[0].GetSize() == 8) + size = STRUCT_FIRST_FIELD_SIZE_IS8; + + fieldType = pFieldStart[1].GetFieldType(); + if (CorTypeInfo::IsPrimitiveType_NoThrow(fieldType)) + { + if (fieldType == ELEMENT_TYPE_R4) + size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND) : (size | STRUCT_FLOAT_FIELD_SECOND); + else if (fieldType == ELEMENT_TYPE_R8) + size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND_8) : (size | STRUCT_SECOND_FIELD_DOUBLE); + else if (pFieldStart[1].GetSize() == 8) + size |= STRUCT_SECOND_FIELD_SIZE_IS8; + goto _End_arg; + } + } + else if (fieldType == ELEMENT_TYPE_VALUETYPE) + { + const NativeFieldDescriptor *pNativeFieldDescs = pMethodTable->GetNativeLayoutInfo()->GetNativeFieldDescriptors(); + + if (pNativeFieldDescs->GetCategory() == NativeFieldCategory::NESTED) + { + MethodTable* pMethodTable2 = pNativeFieldDescs->GetNestedNativeMethodTable(); + + if ((pMethodTable2->GetNumInstanceFieldBytes() > 8) || (pMethodTable2->GetNumIntroducedInstanceFields() > 1)) + goto _End_arg; + size = getLoongArch64PassStructInRegisterFlags((CORINFO_CLASS_HANDLE)pMethodTable2); + if (size == STRUCT_FLOAT_FIELD_ONLY_ONE) + { + if (pFieldStart[0].GetSize() == 8) + size = STRUCT_FIRST_FIELD_DOUBLE; + else + size = STRUCT_FLOAT_FIELD_FIRST; + } + else if (pFieldStart[0].GetSize() == 8) + { + size = STRUCT_FIRST_FIELD_SIZE_IS8; + } + else + size = STRUCT_NO_FLOAT_FIELD; + } + else if (pNativeFieldDescs->GetCategory() == NativeFieldCategory::FLOAT) + { + if (pNativeFieldDescs->NativeSize() == 4) + { + size = STRUCT_FLOAT_FIELD_FIRST; + } + else if (pNativeFieldDescs->NativeSize() == 8) + { + size = STRUCT_FIRST_FIELD_DOUBLE; + } + else + { + UNREACHABLE_MSG("Invalid NativeFieldCategory.----LoongArch64----2"); + } + } + else + { + MethodTable* pMethodTable2 = pFieldStart[0].GetFieldTypeHandleThrowing().AsMethodTable(); + if (pMethodTable2->GetNumIntroducedInstanceFields() == 1) + { + size = getLoongArch64PassStructInRegisterFlags((CORINFO_CLASS_HANDLE)pMethodTable2); + if (size == STRUCT_FLOAT_FIELD_ONLY_ONE) + { + if (pFieldStart[0].GetSize() == 8) + size = STRUCT_FIRST_FIELD_DOUBLE; + else + size = STRUCT_FLOAT_FIELD_FIRST; + } + else if (pFieldStart[0].GetSize() == 8) + { + size = STRUCT_FIRST_FIELD_SIZE_IS8; + } + else + size = STRUCT_NO_FLOAT_FIELD; + } + else + goto _End_arg; + } + } + else if (pFieldStart[0].GetSize() == 8) + size = STRUCT_FIRST_FIELD_SIZE_IS8; + + fieldType = pFieldStart[1].GetFieldType(); + if (CorTypeInfo::IsPrimitiveType_NoThrow(fieldType)) + { + if (fieldType == ELEMENT_TYPE_R4) + size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND) : (size | STRUCT_FLOAT_FIELD_SECOND); + else if (fieldType == ELEMENT_TYPE_R8) + size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND_8) : (size | STRUCT_SECOND_FIELD_DOUBLE); + else if (pFieldStart[1].GetSize() == 8) + size |= STRUCT_SECOND_FIELD_SIZE_IS8; + } + else if (fieldType == ELEMENT_TYPE_VALUETYPE) + { + MethodTable* pMethodTable2 = pFieldStart[1].GetFieldTypeHandleThrowing().AsMethodTable(); + if ((pMethodTable2->GetNumInstanceFieldBytes() > 8) || (pMethodTable2->GetNumIntroducedInstanceFields() > 1)) + { + size = STRUCT_NO_FLOAT_FIELD; + goto _End_arg; + } + if (pMethodTable2->HasLayout()) + { + const NativeFieldDescriptor *pNativeFieldDescs = pMethodTable2->GetNativeLayoutInfo()->GetNativeFieldDescriptors(); + + if (pNativeFieldDescs->NativeSize() > 8) + { + size = STRUCT_NO_FLOAT_FIELD; + goto _End_arg; + } + + if (pNativeFieldDescs->GetCategory() == NativeFieldCategory::NESTED) + { + pMethodTable = pNativeFieldDescs->GetNestedNativeMethodTable(); + + if (pMethodTable->GetNumIntroducedInstanceFields() > 1) + { + size = STRUCT_NO_FLOAT_FIELD; + goto _End_arg; + } + + if (getLoongArch64PassStructInRegisterFlags((CORINFO_CLASS_HANDLE)pMethodTable) == STRUCT_FLOAT_FIELD_ONLY_ONE) + { + if (pMethodTable->GetNumInstanceFieldBytes() == 4) + size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND) : (size | STRUCT_FLOAT_FIELD_SECOND); + else if (pMethodTable->GetNumInstanceFieldBytes() == 8) + size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND_8) : (size | STRUCT_SECOND_FIELD_DOUBLE); + } + else if (pMethodTable->GetNumInstanceFieldBytes() == 8) + size |= STRUCT_SECOND_FIELD_SIZE_IS8; + else + { + size = STRUCT_NO_FLOAT_FIELD; + } + } + else if (pNativeFieldDescs->GetCategory() == NativeFieldCategory::FLOAT) + { + if (pNativeFieldDescs->NativeSize() == 4) + { + size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND) : (size | STRUCT_FLOAT_FIELD_SECOND); + } + else if (pNativeFieldDescs->NativeSize() == 8) + { + size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND_8) : (size | STRUCT_SECOND_FIELD_DOUBLE); + } + else + { + UNREACHABLE_MSG("Invalid NativeFieldCategory.----LoongArch64----3"); + } + } + else + { + if (pNativeFieldDescs->GetNumElements() == 1) + { + fieldType = pNativeFieldDescs->GetFieldDesc()[0].GetFieldType(); + if (fieldType == ELEMENT_TYPE_R4) + size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND) : (size | STRUCT_FLOAT_FIELD_SECOND); + else if (fieldType == ELEMENT_TYPE_R8) + size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND_8) : (size | STRUCT_SECOND_FIELD_DOUBLE); + else if ((size & STRUCT_FLOAT_FIELD_FIRST) == 0) + { + size = STRUCT_NO_FLOAT_FIELD; + goto _End_arg; + } + else if (pNativeFieldDescs->NativeSize() == 8) + size |= STRUCT_SECOND_FIELD_SIZE_IS8; + } + else + { + size = STRUCT_NO_FLOAT_FIELD; + } + } + } + else + { + if (getLoongArch64PassStructInRegisterFlags((CORINFO_CLASS_HANDLE)pMethodTable2) == 1) + { + if (pMethodTable2->GetNumInstanceFieldBytes() == 4) + size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND) : (size | STRUCT_FLOAT_FIELD_SECOND); + else if (pMethodTable2->GetNumInstanceFieldBytes() == 8) + size = size & STRUCT_FLOAT_FIELD_FIRST ? (size ^ STRUCT_MERGE_FIRST_SECOND_8) : (size | STRUCT_SECOND_FIELD_DOUBLE); + } + else if (pMethodTable2->GetNumInstanceFieldBytes() == 8) + size |= STRUCT_SECOND_FIELD_SIZE_IS8; + } + } + else if (pFieldStart[1].GetSize() == 8) + size |= STRUCT_SECOND_FIELD_SIZE_IS8; + } + } + } +_End_arg: + + EE_TO_JIT_TRANSITION_LEAF(); + + return size; +} + /*********************************************************************/ CORINFO_CLASS_HANDLE CEEInfo::getArgClass (